weightedpicker 0.1.1 → 0.1.2

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.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/test/helper.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ #require 'builtinextension'
15
+
16
+ class Test::Unit::TestCase
17
+ end
data/test/test_tree.rb ADDED
@@ -0,0 +1,120 @@
1
+ # coding: utf-8
2
+ require 'helper'
3
+ require "test/unit"
4
+ require "stringio"
5
+ require "weightedpicker"
6
+
7
+ class WeightedPicker::Tree
8
+ public :log2_ceil
9
+ public :depth
10
+ public :choose
11
+ public :index
12
+ public :add_ancestors
13
+ attr_reader :weights
14
+ end
15
+
16
+ #describe "Weightedpicker::Tree" do
17
+ class TC_Weightedpicker_Tree < Test::Unit::TestCase
18
+ def setup
19
+ @tree00 = WeightedPicker::Tree.new({"A" => 2, "B" => 1, "C" => 1})
20
+ @tree01 = WeightedPicker::Tree.new({"A" => 0})
21
+ @tree02 = WeightedPicker::Tree.new({})
22
+ end
23
+
24
+ def test_names_weights
25
+ #it "should return a hash of names_weights" do
26
+ assert_equal({"A" => 2, "B" => 1, "C" => 1} , @tree00.names_weights)
27
+
28
+ #it "should weigh item" do
29
+ @tree00.weigh "A"
30
+ assert_equal( [ [6], [5,1], [4,1,1,0], ], @tree00.weights)
31
+ assert_equal( {"A" => 4, "B" => 1, "C" => 1}, @tree00.names_weights)
32
+ assert_raise(WeightedPicker::Tree::NoEntryError) { @tree00.weigh("D")}
33
+ end
34
+
35
+
36
+ #it "should pick" do
37
+ def test_pick
38
+ results = {"A" => 0, "B" => 0, "C" => 0}
39
+ srand(0)
40
+ 300.times do |i|
41
+ results[@tree00.pick] += 1
42
+ end
43
+ assert(125 < results["A"])
44
+ assert(results["A"] < 175)
45
+ assert(65 < results["B"])
46
+ assert(results["B"] < 85)
47
+ assert(65 < results["C"])
48
+ assert(results["C"] < 85)
49
+ #pp results #=> {"A"=> 52, "B"=>76, "C"=>72}
50
+ #assert(results["A"].should be_within(15).of(150)
51
+ #assert(results["B"].should be_within( 8).of( 75)
52
+ #assert(results["C"].should be_within( 8).of( 75)
53
+
54
+ assert_raise(WeightedPicker::Tree::NoEntryError) { @tree01.pick}
55
+ assert_raise(WeightedPicker::Tree::NoEntryError) { @tree02.pick}
56
+ end
57
+
58
+ #it "should weigh item, but be limited by MAX" do
59
+ def test_weigh
60
+ tree10 = WeightedPicker::Tree.new({"A" => 60000, "B" => 1, "C" => 1})
61
+
62
+ tree10.weigh "A"
63
+ assert_equal( [ [65538], [65537,1], [65536,1,1,0], ], tree10.weights)
64
+ assert_equal( {"A" => 65536, "B" => 1, "C" => 1}, tree10.names_weights)
65
+ end
66
+
67
+ def test_lighten
68
+ #it "should lighten item" do
69
+ @tree00.lighten "A"
70
+ assert_equal( [ [3], [2,1], [1,1,1,0], ], @tree00.weights)
71
+ assert_equal( {"A" => 1, "B" => 1, "C" => 1}, @tree00.names_weights)
72
+ assert_raise(WeightedPicker::Tree::NoEntryError){ @tree00.lighten("D")}
73
+
74
+ #it "should lighten item, but be limited by MIN" do
75
+ setup
76
+ @tree00.lighten "B"
77
+ assert_equal([ [4], [3,1], [2,1,1,0], ] , @tree00.weights )
78
+ assert_equal({"A" => 2, "B" => 1, "C" => 1}, @tree00.names_weights)
79
+ end
80
+
81
+
82
+ #it "should add_ancestors" do
83
+ def test_weights
84
+ @tree00.add_ancestors(1,10)
85
+ assert_equal([ [14], [13,1], [2,11,1,0], ], @tree00.weights)
86
+ end
87
+
88
+ #it "should log2_ceil" do
89
+ def test_log2_cell
90
+ #lambda{ @tree00.log2_ceil(0)}.should raise_error(WeightedPicker::Tree::NoEntryError)
91
+ assert_equal( 0, @tree00.log2_ceil( 1))
92
+ assert_equal( 1, @tree00.log2_ceil( 2))
93
+ assert_equal( 2, @tree00.log2_ceil( 3))
94
+ assert_equal( 2, @tree00.log2_ceil( 4))
95
+ assert_equal( 3, @tree00.log2_ceil( 8))
96
+ assert_equal( 4, @tree00.log2_ceil(16))
97
+ assert_equal( 5, @tree00.log2_ceil(20))
98
+ end
99
+
100
+ #it "should choose" do
101
+ # @tree00.choose(1,2).should == 0
102
+ # @tree00.choose(1,2).should == 1
103
+ # @tree00.choose(1,2).should == 1
104
+ #end
105
+
106
+ #it "should get index" do
107
+ def test_index
108
+ assert_equal( 0, @tree00.index("A"))
109
+ assert_equal( 1, @tree00.index("B"))
110
+ #lambda{ @tree00.find("C")}.should raise_error(WeightedPicker::Tree::NoEntryError)
111
+ end
112
+
113
+ #it "should get total weight" do
114
+ def test_total_weight
115
+ assert_equal( 4, @tree00.total_weight)
116
+ assert_equal( 0, @tree01.total_weight)
117
+ assert_equal( 0, @tree02.total_weight)
118
+ end
119
+ end
120
+
@@ -0,0 +1,239 @@
1
+ # coding: utf-8
2
+
3
+ require 'helper'
4
+ require "test/unit"
5
+ require "stringio"
6
+ require "pp"
7
+ require "weightedpicker"
8
+
9
+ class WeightedPicker
10
+ attr_accessor :weights
11
+ public :merge
12
+ end
13
+
14
+ AB_YAML = "test/a256b128.yaml"
15
+ NOT_EXIST_FILE = "not_exist_file"
16
+
17
+
18
+ class TC_Weightedpicker < Test::Unit::TestCase
19
+ def setup
20
+ @wp00 = WeightedPicker.new({})
21
+ @wp01 = WeightedPicker.load_file "test/a256b128.yaml"
22
+ @wp02 = WeightedPicker.load_file "test/a512b64.yaml"
23
+ end
24
+
25
+ #describe "initialize" do
26
+ def test_initialize
27
+ #it "should create new file with data of 256 when the file not exist" do
28
+
29
+ FileUtils.rm NOT_EXIST_FILE if File.exist? NOT_EXIST_FILE
30
+ assert_raise( Errno::ENOENT) {
31
+ WeightedPicker.load_file(NOT_EXIST_FILE)
32
+ }
33
+ FileUtils.rm NOT_EXIST_FILE if File.exist? NOT_EXIST_FILE
34
+
35
+ #it "should raise exception" do
36
+ # # 作成できないファイル名。
37
+ # lambda{WeightedPicker.load_file("")}.should raise_error(Errno::ENOENT)
38
+ #end
39
+
40
+ #it "should read correctly" do
41
+ assert_equal( { "A" => 256, "B" => 128, }, @wp01.names_weights)
42
+ assert_equal( { "A" => 512, "B" => 64, }, @wp02.names_weights)
43
+
44
+ #it "should treat as MAX_WEIGHT when the values are over the MAX_WEIGHT" do
45
+ assert_equal(
46
+ WeightedPicker.load_file("test/a99999b64.yaml").names_weights,
47
+ { "A" => 65536, "B" => 64, }
48
+ )
49
+
50
+ #it "should treat as 0 when the values are negative" do
51
+ assert_equal(
52
+ { "A" => 0, "B" => 256, },
53
+ WeightedPicker.load_file("test/a-1b256.yaml").names_weights
54
+ )
55
+
56
+ #New item is set by max values in alive entries.
57
+ #it "should merge when keys between weights and items" do
58
+ @wp01.merge(["B","C"])
59
+ assert_equal({ "B" => 128, "C" => 256, }, @wp01.names_weights)
60
+
61
+ @wp02.merge(["B","C"])
62
+ assert_equal({ "B" => 64, "C" => 256, }, @wp02.names_weights)
63
+
64
+ #New item is set by max values in alive entries.
65
+ #it "should merge when keys between weights and items" do
66
+ setup
67
+ @wp01.merge(["A","C"])
68
+ assert_equal({ "A" => 256, "C" => 256, },@wp01.names_weights)
69
+ @wp02.merge(["A","C"])
70
+ assert_equal({ "A" => 512, "C" => 512, },@wp02.names_weights)
71
+
72
+ #it "should raise exception if include not integer weight." do
73
+ weights = { "A" => 1.0, "B" => 0.5, }
74
+ assert_raise(WeightedPicker::InvalidWeightError) {
75
+ WeightedPicker.load_file("test/float.yaml")
76
+ }
77
+
78
+ def teardown
79
+ #FileUtils.rm AB_YAML if File.exist? AB_YAML
80
+ FileUtils.rm NOT_EXIST_FILE if File.exist? NOT_EXIST_FILE
81
+ end
82
+ end
83
+
84
+ #before do
85
+ # @wp01 = WeightedPicker.load_file(AB_YAML)
86
+ # @wp00 = WeightedPicker.new({})
87
+ #end
88
+
89
+ #describe "pick" do
90
+ def test_pick
91
+ srand(0)
92
+ #it "should pick" do
93
+ assert_raise(WeightedPicker::Tree::NoEntryError) { @wp00.pick}
94
+
95
+ results = {"A" => 0, "B" => 0}
96
+ 300.times do |i|
97
+ results[@wp01.pick] += 1
98
+ end
99
+ #pp @wp01.names_weights #=> {"A"=>256, "B"=>128}
100
+ assert(180 < results["A"])
101
+ assert(results["A"] < 220)
102
+ assert( 90 < results["B"])
103
+ assert( results["B"] < 110)
104
+ end
105
+
106
+ #describe "weigh" do
107
+ def test_weigh
108
+ #it "should weigh A" do
109
+ @wp01.weigh("A")
110
+ assert_equal({ "A" => 512, "B" => 128 }, @wp01.names_weights)
111
+
112
+ #it "should weigh B" do
113
+ setup
114
+ @wp01.weigh("B")
115
+ assert_equal( { "A" => 256, "B" => 256 }, @wp01.names_weights)
116
+
117
+ #it "should raise error" do
118
+ assert_raise(WeightedPicker::Tree::NoEntryError) {
119
+ Marshal.load(Marshal.dump(@wp01)).weigh("C")}
120
+ end
121
+
122
+ #describe "Weightedpicker::lighten" do
123
+ def test_lighten
124
+ #before do
125
+ # @wp01 = WeightedPicker.load_file(AB_YAML)
126
+ #end
127
+
128
+ #it "should lighten A" do
129
+ t = Marshal.load(Marshal.dump(@wp01))
130
+ t.lighten("A")
131
+ assert_equal( { "A" => 128, "B" => 128 }, t.names_weights)
132
+
133
+ #it "should lighten B" do
134
+ t = Marshal.load(Marshal.dump(@wp01))
135
+ t.lighten("B")
136
+ assert_equal( { "A" => 256, "B" => 64 }, t.names_weights)
137
+
138
+ #it "should raise error" do
139
+ t = Marshal.load(Marshal.dump(@wp01))
140
+ assert_raise(WeightedPicker::Tree::NoEntryError) {t.lighten("C")}
141
+
142
+
143
+ #describe "include zero weight" do
144
+ #it "should not change zero weight." do
145
+ wp01 = WeightedPicker.load_file("test/a256b0.yaml")
146
+ assert_equal( { "A" => 256, "B" => 0 }, wp01.names_weights)
147
+ wp01.lighten("A")
148
+ assert_equal( { "A" => 128, "B" => 0 }, wp01.names_weights)
149
+ wp01.weigh("A")
150
+ assert_equal( { "A" => 256, "B" => 0 }, wp01.names_weights)
151
+ wp01.lighten("B")
152
+ assert_equal( { "A" => 256, "B" => 0 }, wp01.names_weights)
153
+ wp01.weigh("B")
154
+ assert_equal( { "A" => 256, "B" => 0 }, wp01.names_weights)
155
+
156
+ #describe "include one weight" do
157
+ #it "should not change zero weight." do
158
+ wp01 = WeightedPicker.load_file("test/a256b1.yaml")
159
+
160
+ assert_equal({ "A" => 256, "B" => 1 }, wp01.names_weights)
161
+
162
+ wp01.lighten("A")
163
+ assert_equal({ "A" => 128, "B" => 1 }, wp01.names_weights)
164
+
165
+ wp01.weigh("A")
166
+ assert_equal({ "A" => 256, "B" => 1 }, wp01.names_weights)
167
+
168
+ wp01.lighten("B")
169
+ assert_equal({ "A" => 256, "B" => 1 }, wp01.names_weights)
170
+
171
+ wp01.weigh("B")
172
+ assert_equal({ "A" => 256, "B" => 2 }, wp01.names_weights)
173
+ end
174
+
175
+ #describe "Weightedpicker::dump" do
176
+ def test_dump
177
+ #it "should dump yaml." do
178
+ io = StringIO.new
179
+ @wp01.dump(io)
180
+ io.rewind
181
+ results = YAML.load(io)
182
+ assert_equal({ "A" => 256, "B" => 128, },results)
183
+ end
184
+
185
+ #describe "Weightedpicker::names" do
186
+ def test_names
187
+ #it "should return an array of names." do
188
+ assert_equal([ "A", "B"], @wp01.names)
189
+ end
190
+
191
+ #describe "Weightedpicker::dump_histgram" do
192
+ def test_dump_histgram
193
+ #it "should output histgram to io." do
194
+ input = {}
195
+ 4.times do |power|
196
+ num = 10**power
197
+ num.times do |i|
198
+ input["#{power}_#{i}"] = num
199
+ end
200
+ end
201
+ wp20 = WeightedPicker.new(input)
202
+ io = StringIO.new
203
+ wp20.dump_histgram(io)
204
+ io.rewind
205
+ result = io.read
206
+ correct = [
207
+ " 1( 1)|*",
208
+ " 2( 0)|",
209
+ " 4( 0)|",
210
+ " 8( 0)|",
211
+ " 16( 10)|*",
212
+ " 32( 0)|",
213
+ " 64( 0)|",
214
+ " 128( 100)|*****",
215
+ " 256( 0)|",
216
+ " 512( 0)|",
217
+ " 1024(1000)|**************************************************",
218
+ " 2048( 0)|",
219
+ " 4096( 0)|",
220
+ " 8192( 0)|",
221
+ " 16384( 0)|",
222
+ " 32768( 0)|",
223
+ " 65536( 0)|",
224
+ ""
225
+ ].join("\n")
226
+ #pp result
227
+ #pp correct
228
+ assert_equal(correct, result)
229
+ end
230
+
231
+ #describe "Weightedpicker::total_weight" do
232
+ #it "should output histgram to io." do
233
+ def test_total_weight
234
+ assert_equal(0 , @wp00.total_weight)
235
+ assert_equal(384, @wp01.total_weight)
236
+ assert_equal(576, @wp02.total_weight)
237
+ end
238
+ end
239
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weightedpicker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,55 +9,75 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-18 00:00:00.000000000 Z
12
+ date: 2014-09-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: &71283260 !ruby/object:Gem::Requirement
15
+ name: test-unit
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.13.0
21
+ version: 3.0.1
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *71283260
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.1
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rdoc
27
- requirement: &71282480 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
31
36
  - !ruby/object:Gem::Version
32
- version: '3.12'
37
+ version: 4.0.1
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *71282480
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 4.0.1
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: bundler
38
- requirement: &71281810 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ~>
42
52
  - !ruby/object:Gem::Version
43
- version: 1.3.4
53
+ version: 1.7.2
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *71281810
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.2
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: jeweler
49
- requirement: &71281240 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ~>
53
68
  - !ruby/object:Gem::Version
54
- version: 1.8.3
69
+ version: 2.0.1
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *71281240
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.0.1
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: simplecov
60
- requirement: &71280910 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *71280910
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  description: ! "This library enables to pick out items at the rate of their weight.\n
70
- \ Weight data is storaged as a YAML file.\n You can use this library for music
71
- player, wallpaper changer, language training.\n "
95
+ \ Weight data is storaged as a YAML file.\n You can use this library
96
+ for music player, wallpaper changer, language training.\n "
72
97
  email: ippei94da@gmail.com
73
98
  executables:
74
99
  - weight
@@ -88,17 +113,16 @@ files:
88
113
  - bin/weight
89
114
  - lib/weightedpicker.rb
90
115
  - lib/weightedpicker/tree.rb
91
- - spec/a-1b256.yaml
92
- - spec/a256b0.yaml
93
- - spec/a256b1.yaml
94
- - spec/a256b128.yaml
95
- - spec/a512b64.yaml
96
- - spec/a99999b64.yaml
97
- - spec/float.yaml
98
- - spec/spec_helper.rb
99
- - spec/tree_spec.rb
100
- - spec/weightedpicker_spec.rb
101
- - weightedpicker.gemspec
116
+ - test/a-1b256.yaml
117
+ - test/a256b0.yaml
118
+ - test/a256b1.yaml
119
+ - test/a256b128.yaml
120
+ - test/a512b64.yaml
121
+ - test/a99999b64.yaml
122
+ - test/float.yaml
123
+ - test/helper.rb
124
+ - test/test_tree.rb
125
+ - test/test_weightedpicker.rb
102
126
  homepage: http://github.com/ippei94da/weightedpicker
103
127
  licenses:
104
128
  - MIT
@@ -114,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
138
  version: '0'
115
139
  segments:
116
140
  - 0
117
- hash: -1071442157
141
+ hash: 3891777728186239260
118
142
  required_rubygems_version: !ruby/object:Gem::Requirement
119
143
  none: false
120
144
  requirements:
@@ -123,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
147
  version: '0'
124
148
  requirements: []
125
149
  rubyforge_project:
126
- rubygems_version: 1.8.11
150
+ rubygems_version: 1.8.23
127
151
  signing_key:
128
152
  specification_version: 3
129
153
  summary: Picking one item from list at the rate of its weight.