top_n 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a5fc5435e211281c5d59fa26d155260a0359a216
4
+ data.tar.gz: f3cd1bf16b9c9c11ad87793a7c0741e1fe7f314a
5
+ SHA512:
6
+ metadata.gz: 471670b61a3b91ff867fab94bcd414a9f766fb7367579122ea57d5f4d58e7b964e4551d77bb4ce35a4b2523df7282dce8a845791c0c8c7677ff4ec46c82b4071
7
+ data.tar.gz: 24330b140e01c80493d4434720672bef428825bbb8a6133ab234443c77bf498583f4c91360e2a33524da9d4e02a20814ec450a33ed14498a3dbe1c6b435eb08b
@@ -0,0 +1,12 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 1.9.3
4
+ - rbx
5
+ - rbx-2
6
+ - jruby-19mode
7
+
8
+ before_script:
9
+
10
+ notifications:
11
+ email:
12
+ - explorer@flame.org
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "minitest", ">= 0"
10
+ gem "yard", "~> 0.7"
11
+ gem "rdoc", "~> 3.12"
12
+ gem "bundler", "~> 1.0"
13
+ gem "jeweler", "~> 1.8.7"
14
+ gem "guard"
15
+ gem 'guard-minitest'
16
+
17
+ platforms :rbx do
18
+ # gem 'racc'
19
+ gem 'rubysl'
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest do
5
+ # with Minitest::Unit
6
+ watch(%r{^test/(.*)\/?test_(.*)\.rb})
7
+ watch(%r{^lib/(.*/)?([^/]+)\.rb}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
8
+ watch(%r{^test/test_helper\.rb}) { 'test' }
9
+
10
+ # with Minitest::Spec
11
+ # watch(%r{^spec/(.*)_spec\.rb})
12
+ # watch(%r{^lib/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
13
+ # watch(%r{^spec/spec_helper\.rb}) { 'spec' }
14
+
15
+ # Rails 4
16
+ # watch(%r{^app/(.+)\.rb}) { |m| "test/#{m[1]}_test.rb" }
17
+ # watch(%r{^app/controllers/application_controller\.rb}) { 'test/controllers' }
18
+ # watch(%r{^app/controllers/(.+)_controller\.rb}) { |m| "test/integration/#{m[1]}_test.rb" }
19
+ # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
20
+ # watch(%r{^lib/(.+)\.rb}) { |m| "test/lib/#{m[1]}_test.rb" }
21
+ # watch(%r{^test/.+_test\.rb})
22
+ # watch(%r{^test/test_helper\.rb}) { 'test' }
23
+
24
+ # Rails < 4
25
+ # watch(%r{^app/controllers/(.*)\.rb}) { |m| "test/functional/#{m[1]}_test.rb" }
26
+ # watch(%r{^app/helpers/(.*)\.rb}) { |m| "test/helpers/#{m[1]}_test.rb" }
27
+ # watch(%r{^app/models/(.*)\.rb}) { |m| "test/unit/#{m[1]}_test.rb" }
28
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Michael Graff
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ = top_n
2
+
3
+ {<img src="https://travis-ci.org/skandragon/top_n.png?branch=master" alt="Build Status" />}[https://travis-ci.org/skandragon/top_n]
4
+
5
+ This gem allows tracking of the top N (or bottom N) keys added to a list.
6
+ Each key can have an optional value, which is then added to a list of values for that key.
7
+
8
+ Key types must respond to the usual comparison operators: <, <=, >, >=, and <=>. Values may be any object type, and need not be unique. Values are not examined in any way, simply added to an internal list.
9
+
10
+ If a <key, value> pair is added twice, it will store the value twice for that key, and return it twice in the list for that key, when that key is retrieved.
11
+
12
+ Once the top N keys are added, adding smaller keys will be ignored. Adding a larger key will drop the then-smallest value. Adding another value at an existing key will simply result in
13
+
14
+ For example, track the top 1,000 EverQuest 2 characters with the highest strenth, the most quests completed, or items crafted, out of the roughly 2.4 million characters which currently exist.
15
+
16
+ == Contributing to this project
17
+
18
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
19
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
20
+ * Fork the project.
21
+ * Start a feature/bugfix branch.
22
+ * Commit and push until you are happy with your contribution.
23
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
24
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
25
+
26
+ == Copyright
27
+
28
+ Copyright (c) 2013 Michael Graff. See LICENSE.txt for
29
+ further details.
30
+
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "top_n"
18
+ gem.homepage = "http://github.com/skandragon/top_n"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Track the top (or bottom) N keys added to a list}
21
+ gem.description = %Q{Track the top (or bottom) N keys added to a list, and discard the remainder.}
22
+ gem.email = "explorer@flame.org"
23
+ gem.authors = ["Michael Graff"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'yard'
38
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,178 @@
1
+ ##
2
+ # This class tracks the top (or bottom) N values for a set of keys.
3
+ #
4
+ # As keys and values are added, only the largest (or smallest) keys will
5
+ # be recorded. As larger (or smaller) keys are added, unneeded items are
6
+ # removed.
7
+ #
8
+ # Keys may be any object that is comparable with < and >. Values may be
9
+ # any object, and are not processed beyond appending them to an internal
10
+ # list.
11
+ #
12
+ # @note
13
+ # Note that while the number of keys is restricted, the values are not.
14
+ # This can cause memory issues if many values are added to the same key.
15
+ # If this is the type of data you are tracking, you may need a different
16
+ # solution.
17
+ class TopN
18
+ # The maxinum number of keys which will be tracked.
19
+ # @return [Fixnum] the configured maximum number of keys to be tracked.
20
+ attr_reader :maxsize
21
+
22
+ # The configured direction.
23
+ # @return [Symbol] either :top or :bottom.
24
+ attr_reader :direction
25
+
26
+ # The current number of keys we are tracking.
27
+ # @return [FixNum] the count, which will be 0 up to :maxsize.
28
+ attr_reader :size
29
+
30
+ # The current value of the minimum (:top) or maximum (:bottom) key.
31
+ # @return [Object] the threshold key.
32
+ attr_reader :threshold_key
33
+
34
+ # The currently tracked data as one blob. This is tied to the
35
+ # current implementation, so its use is not recommended.
36
+ # @return [Hash] the internal data structure containing the keys and
37
+ # values. The keys to the returned Hash are the tracked keys, and
38
+ # the values at those keys is the list of values.
39
+ attr_reader :data
40
+
41
+ ##
42
+ # Create a new TopN object. Options available:
43
+ #
44
+ # @param [Hash] options the options used to configure the TopN object.
45
+ #
46
+ # @option options [Fixnum] :maxsize The maximum number of keys to track.
47
+ # Must be a positive Fixnum. Defaults to 100.
48
+ #
49
+ # @option options [Symbol] :direction Configure the direction.
50
+ # If this is :top, the largest keys will be maintained. If :bottom,
51
+ # the smallest keys will be maintained. Any other value throws an
52
+ # exception.
53
+ # Defaults to :top.
54
+ #
55
+ # @raise [ArgumentError] if an invalid value is detected for any option.
56
+ #
57
+ # @example Create with default options
58
+ # topn = TopN.new
59
+ #
60
+ # @example Create with a maximum size of 10, and track smaller values
61
+ # topn = TopN.new(maxsize: 10, direction: :bottom)
62
+ #
63
+ def initialize(options = {})
64
+ options = {
65
+ maxsize: 100,
66
+ direction: :top,
67
+ }.merge(options)
68
+
69
+ @maxsize = options[:maxsize]
70
+ @direction = options[:direction]
71
+ @data = {}
72
+ @size = 0
73
+ @threshold_key = nil
74
+
75
+ unless [:top, :bottom].include?(@direction)
76
+ raise ArgumentError.new("direction must be :top or :bottom")
77
+ end
78
+
79
+ unless @maxsize.is_a?Fixnum
80
+ raise ArgumentError.new("maxsize must be a Fixnum")
81
+ end
82
+
83
+ if @maxsize <= 0
84
+ raise ArgumentError.new("maxsize must be >= 1")
85
+ end
86
+ end
87
+
88
+ ##
89
+ # Add a key, value pair.
90
+ #
91
+ # @param [Object] key the key, which must be compariable with < and >.
92
+ # @param [Object] value the value, which is added to the key's list of
93
+ # values. Adding the same value to a key multiple times results in
94
+ # duplicate values being recorded.
95
+ #
96
+ # If the key already exists, the value will be appended to the existing list
97
+ # of values at that key.
98
+ #
99
+ # If an existing (key, value) is permitted, and will result in the list of
100
+ # values at that key having the same value multiple times.
101
+ #
102
+ # @return [Array] if the value was added to the key's list.
103
+ #
104
+ # @return [nil] if the value was not added because the key is too small or
105
+ # large to be tracked.
106
+ def add(key, value)
107
+ if @direction == :top
108
+ add_top(key, value)
109
+ else
110
+ add_bottom(key, value)
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Find and return the list of values for a key.
116
+ #
117
+ # @return [Array<Object>] the list of values for 'key'.
118
+ #
119
+ # @return [nil] if the key does not exist.
120
+ def find(key)
121
+ @data[key]
122
+ end
123
+
124
+ ##
125
+ # Return the list of currently tracked keys.
126
+ #
127
+ # @return [Array<Object>] the list of values for this key.
128
+ # Order is not guaranteed to match the oder which they were added.
129
+ def keys
130
+ @data.keys
131
+ end
132
+
133
+ private
134
+
135
+ ##
136
+ # Add a (key, value) when the direction is :top.
137
+ def add_top(key, value)
138
+ @threshold_key ||= key
139
+
140
+ if @size >= @maxsize
141
+ return nil if key < @threshold_key
142
+ @data.delete(@threshold_key)
143
+ end
144
+
145
+ unless @data.has_key?key
146
+ @data[key] = []
147
+ @size += 1 if @size < @maxsize
148
+ end
149
+
150
+ @data[key] << value
151
+
152
+ @threshold_key = key if key < @threshold_key
153
+
154
+ @data[key]
155
+ end
156
+
157
+ ##
158
+ # Add a (key, value) when the direction is :bottom.
159
+ def add_bottom(key, value)
160
+ @threshold_key ||= key
161
+
162
+ if @size >= @maxsize
163
+ return nil if key > @threshold_key
164
+ @data.delete(@threshold_key)
165
+ end
166
+
167
+ unless @data.has_key?key
168
+ @data[key] = []
169
+ @size += 1 if @size < @maxsize
170
+ end
171
+
172
+ @data[key] << value
173
+
174
+ @threshold_key = key if key > @threshold_key
175
+
176
+ @data[key]
177
+ end
178
+ end
@@ -0,0 +1,19 @@
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 'minitest/autorun'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ require 'top_n'
15
+
16
+ class MiniTest::Unit::TestCase
17
+ end
18
+
19
+ MiniTest.autorun
@@ -0,0 +1,88 @@
1
+ require 'helper'
2
+
3
+ class TestAddingBottom < Minitest::Test
4
+ def test_threshold_key_is_nil_on_create
5
+ topn = TopN.new(direction: :bottom)
6
+ assert_nil topn.threshold_key
7
+ end
8
+
9
+ def test_adding_updates_threshold_key
10
+ topn = TopN.new(direction: :bottom)
11
+ assert topn.add(5, 5), "add(5, 5) failed"
12
+ assert_equal 5, topn.threshold_key
13
+ end
14
+
15
+ def test_adding_increments_size
16
+ topn = TopN.new(direction: :bottom)
17
+ assert topn.add(1, 1), "add(1, 1) failed"
18
+ assert topn.size == 1, "size == 1 failed"
19
+ end
20
+
21
+ def test_adding_without_exceeding_adds
22
+ topn = TopN.new(direction: :bottom, maxsize: 10)
23
+ assert topn.add(5, 5), "add(5, 5) failed"
24
+ assert topn.find(5) == [5], "find(5) failed"
25
+ assert_equal 5, topn.threshold_key
26
+ end
27
+
28
+ def test_adding_sets_threshold_key
29
+ topn = TopN.new(direction: :bottom, maxsize: 10)
30
+ assert topn.add(5, 5), "add(5, 5) failed"
31
+ assert topn.find(5) == [5], "find(5) failed"
32
+ assert_equal 5, topn.threshold_key
33
+ end
34
+
35
+ def test_adding_without_exceeding
36
+ topn = TopN.new(direction: :bottom, maxsize: 10)
37
+ assert topn.add(5, 5), "add(5, 5) failed"
38
+ assert topn.add(10, 10), "add(10, 10) failed"
39
+ assert topn.find(5) == [5], "find(5) failed"
40
+ assert topn.find(10) == [10], "find(5) failed"
41
+ assert_equal 10, topn.threshold_key
42
+ end
43
+
44
+ def test_adding_larger_without_exceeding_sets_threshold_key
45
+ topn = TopN.new(direction: :bottom, maxsize: 10)
46
+ assert topn.add(5, 5), "add(5, 5) failed"
47
+ assert_equal 5, topn.threshold_key
48
+ assert topn.add(10, 10), "add(10, 10) failed"
49
+ assert_equal 10, topn.threshold_key
50
+ end
51
+
52
+ def test_adding_smaller_without_exceeding_sets_threshold_key
53
+ topn = TopN.new(direction: :bottom, maxsize: 10)
54
+ assert topn.add(10, 10), "add(10, 10) failed"
55
+ assert_equal 10, topn.threshold_key
56
+ assert topn.add(5, 5), "add(5, 5) failed"
57
+ assert_equal 10, topn.threshold_key
58
+ end
59
+
60
+ def test_adding_two_values_to_the_same_key
61
+ topn = TopN.new(direction: :bottom, maxsize: 10)
62
+ assert topn.add(1, 1), "add(1, 1) failed"
63
+ assert topn.add(1, 2), "add(1, 2) failed"
64
+ assert_equal [1, 2], topn.find(1).sort
65
+ end
66
+
67
+ def test_adding_smaller_key_when_limit_will_exceed
68
+ topn = TopN.new(direction: :bottom, maxsize: 2)
69
+ assert topn.add(3, 3), "add(3, 3) failed"
70
+ assert topn.add(2, 2), "add(2, 2) failed"
71
+ assert topn.add(1, 1), "add(1, 1) failed"
72
+ assert_equal 2, topn.size
73
+ assert_equal [1], topn.find(1)
74
+ assert_equal [2], topn.find(2)
75
+ assert_nil topn.find(3)
76
+ end
77
+
78
+ def test_adding_larger_key_when_limit_will_exceed
79
+ topn = TopN.new(direction: :bottom, maxsize: 2)
80
+ assert topn.add(1, 1), "add(1, 1) failed"
81
+ assert topn.add(2, 2), "add(2, 2) failed"
82
+ assert_nil topn.add(3, 3)
83
+ assert_equal 2, topn.size
84
+ assert_equal [1], topn.find(1)
85
+ assert_equal [2], topn.find(2)
86
+ assert_nil topn.find(3)
87
+ end
88
+ end
@@ -0,0 +1,88 @@
1
+ require 'helper'
2
+
3
+ class TestAddingTop < Minitest::Test
4
+ def test_threshold_key_is_nil_on_create
5
+ topn = TopN.new
6
+ assert_nil topn.threshold_key
7
+ end
8
+
9
+ def test_adding_updates_threshold_key
10
+ topn = TopN.new
11
+ assert topn.add(5, 5), "add(5, 5) failed"
12
+ assert_equal 5, topn.threshold_key
13
+ end
14
+
15
+ def test_adding_increments_size
16
+ topn = TopN.new
17
+ assert topn.add(1, 1), "add(1, 1) failed"
18
+ assert topn.size == 1, "size == 1 failed"
19
+ end
20
+
21
+ def test_adding_without_exceeding_adds
22
+ topn = TopN.new(maxsize: 10)
23
+ assert topn.add(5, 5), "add(5, 5) failed"
24
+ assert topn.find(5) == [5], "find(5) failed"
25
+ assert_equal 5, topn.threshold_key
26
+ end
27
+
28
+ def test_adding_sets_threshold_key
29
+ topn = TopN.new(maxsize: 10)
30
+ assert topn.add(5, 5), "add(5, 5) failed"
31
+ assert topn.find(5) == [5], "find(5) failed"
32
+ assert_equal 5, topn.threshold_key
33
+ end
34
+
35
+ def test_adding_without_exceeding
36
+ topn = TopN.new(maxsize: 10)
37
+ assert topn.add(5, 5), "add(5, 5) failed"
38
+ assert topn.add(10, 10), "add(10, 10) failed"
39
+ assert topn.find(5) == [5], "find(5) failed"
40
+ assert topn.find(10) == [10], "find(5) failed"
41
+ assert_equal 5, topn.threshold_key
42
+ end
43
+
44
+ def test_adding_larger_without_exceeding_sets_threshold_key
45
+ topn = TopN.new(maxsize: 10)
46
+ assert topn.add(5, 5), "add(5, 5) failed"
47
+ assert_equal 5, topn.threshold_key
48
+ assert topn.add(10, 10), "add(10, 10) failed"
49
+ assert_equal 5, topn.threshold_key
50
+ end
51
+
52
+ def test_adding_smaller_without_exceeding_sets_threshold_key
53
+ topn = TopN.new(maxsize: 10)
54
+ assert topn.add(10, 10), "add(10, 10) failed"
55
+ assert_equal 10, topn.threshold_key
56
+ assert topn.add(5, 5), "add(5, 5) failed"
57
+ assert_equal 5, topn.threshold_key
58
+ end
59
+
60
+ def test_adding_two_values_to_the_same_key
61
+ topn = TopN.new(maxsize: 10)
62
+ assert topn.add(1, 1), "add(1, 1) failed"
63
+ assert topn.add(1, 2), "add(1, 2) failed"
64
+ assert_equal [1, 2], topn.find(1).sort
65
+ end
66
+
67
+ def test_adding_larger_key_when_limit_will_exceed
68
+ topn = TopN.new(maxsize: 2)
69
+ assert topn.add(1, 1), "add(1, 1) failed"
70
+ assert topn.add(2, 2), "add(1, 1) failed"
71
+ assert topn.add(3, 3), "add(1, 1) failed"
72
+ assert_equal 2, topn.size
73
+ assert_nil topn.find(1)
74
+ assert_equal [2], topn.find(2)
75
+ assert_equal [3], topn.find(3)
76
+ end
77
+
78
+ def test_adding_smaller_key_when_limit_will_exceed
79
+ topn = TopN.new(maxsize: 2)
80
+ assert topn.add(3, 3), "add(1, 1) failed"
81
+ assert topn.add(2, 2), "add(1, 1) failed"
82
+ assert_nil topn.add(1, 1)
83
+ assert_equal 2, topn.size
84
+ assert_nil topn.find(1)
85
+ assert_equal [2], topn.find(2)
86
+ assert_equal [3], topn.find(3)
87
+ end
88
+ end
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+
3
+ class TestTopN < Minitest::Test
4
+ def test_creation_without_arguments
5
+ topn = TopN.new
6
+ assert topn
7
+ end
8
+
9
+ def test_creation_without_arguments_sets_maxsize_to_some_positive_default
10
+ topn = TopN.new
11
+ assert topn.maxsize > 0
12
+ end
13
+
14
+ def test_creation_with_maxsize
15
+ topn = TopN.new(maxsize: 100)
16
+ assert topn.maxsize == 100
17
+ end
18
+
19
+ def test_creation_with_direction
20
+ topn = TopN.new(direction: :bottom)
21
+ assert topn.direction == :bottom
22
+ end
23
+
24
+ def test_creation_raises_assertion_with_bad_direction
25
+ assert_raises(ArgumentError) {
26
+ TopN.new(direction: :flarg)
27
+ }
28
+ end
29
+
30
+ def test_creation_raises_assertion_with_zero_maxsize
31
+ assert_raises(ArgumentError) {
32
+ TopN.new(maxsize: 0)
33
+ }
34
+ end
35
+
36
+ def test_creation_raises_assertion_with_negative_maxsize
37
+ assert_raises(ArgumentError) {
38
+ TopN.new(maxsize: -1)
39
+ }
40
+ end
41
+
42
+ def test_creation_raises_assertion_with_non_fixnum_maxsize
43
+ assert_raises(ArgumentError) {
44
+ TopN.new(maxsize: 'foo')
45
+ }
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ require 'helper'
2
+
3
+ class TestData < Minitest::Test
4
+ def test_data_is_empty_on_create
5
+ topn = TopN.new(maxsize: 2)
6
+ assert_equal({}, topn.data)
7
+ end
8
+
9
+ def test_data_has_keys
10
+ topn = TopN.new(maxsize: 2)
11
+ assert topn.add(1, 1), "add(1, 1) failed"
12
+ assert topn.add(2, 2), "add(1, 1) failed"
13
+ assert topn.add(3, 3), "add(1, 1) failed"
14
+ assert_equal [2, 3], topn.data.keys.sort
15
+ end
16
+
17
+ def test_keys
18
+ topn = TopN.new(maxsize: 2)
19
+ assert topn.add(1, 1), "add(1, 1) failed"
20
+ assert topn.add(2, 2), "add(1, 1) failed"
21
+ assert topn.add(3, 3), "add(1, 1) failed"
22
+ assert_equal [2, 3], topn.keys.sort
23
+ end
24
+ end
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "top_n"
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Michael Graff"]
12
+ s.date = "2013-12-15"
13
+ s.description = "Track the top (or bottom) N keys added to a list, and discard the remainder."
14
+ s.email = "explorer@flame.org"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".travis.yml",
21
+ "Gemfile",
22
+ "Guardfile",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/top_n.rb",
28
+ "test/helper.rb",
29
+ "test/test_adding_bottom.rb",
30
+ "test/test_adding_top.rb",
31
+ "test/test_creation.rb",
32
+ "test/test_data.rb",
33
+ "top_n.gemspec"
34
+ ]
35
+ s.homepage = "http://github.com/skandragon/top_n"
36
+ s.licenses = ["MIT"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = "2.0.14"
39
+ s.summary = "Track the top (or bottom) N keys added to a list"
40
+
41
+ if s.respond_to? :specification_version then
42
+ s.specification_version = 4
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ s.add_development_dependency(%q<minitest>, [">= 0"])
46
+ s.add_development_dependency(%q<yard>, ["~> 0.7"])
47
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
48
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
50
+ s.add_development_dependency(%q<guard>, [">= 0"])
51
+ s.add_development_dependency(%q<guard-minitest>, [">= 0"])
52
+ s.add_development_dependency(%q<rubysl>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<minitest>, [">= 0"])
55
+ s.add_dependency(%q<yard>, ["~> 0.7"])
56
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
59
+ s.add_dependency(%q<guard>, [">= 0"])
60
+ s.add_dependency(%q<guard-minitest>, [">= 0"])
61
+ s.add_dependency(%q<rubysl>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<minitest>, [">= 0"])
65
+ s.add_dependency(%q<yard>, ["~> 0.7"])
66
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
69
+ s.add_dependency(%q<guard>, [">= 0"])
70
+ s.add_dependency(%q<guard-minitest>, [">= 0"])
71
+ s.add_dependency(%q<rubysl>, [">= 0"])
72
+ end
73
+ end
74
+
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: top_n
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Graff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 1.8.7
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.8.7
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubysl
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Track the top (or bottom) N keys added to a list, and discard the remainder.
126
+ email: explorer@flame.org
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files:
130
+ - LICENSE.txt
131
+ - README.rdoc
132
+ files:
133
+ - .travis.yml
134
+ - Gemfile
135
+ - Guardfile
136
+ - LICENSE.txt
137
+ - README.rdoc
138
+ - Rakefile
139
+ - VERSION
140
+ - lib/top_n.rb
141
+ - test/helper.rb
142
+ - test/test_adding_bottom.rb
143
+ - test/test_adding_top.rb
144
+ - test/test_creation.rb
145
+ - test/test_data.rb
146
+ - top_n.gemspec
147
+ homepage: http://github.com/skandragon/top_n
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.0.14
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Track the top (or bottom) N keys added to a list
171
+ test_files: []