geohash36 0.3.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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS.md +29 -0
  3. data/CHANGELOG.md +0 -0
  4. data/COPYING.md +12 -0
  5. data/Gemfile +107 -0
  6. data/LICENSE.md +14 -0
  7. data/MAINTAINERS.md +40 -0
  8. data/README.md +78 -0
  9. data/Rakefile +52 -0
  10. data/bin/geohash36 +45 -0
  11. data/geohash36.gemspec +136 -0
  12. data/lib/demo.rb +25 -0
  13. data/lib/geohash36/interface/rake/cucumber.rb +36 -0
  14. data/lib/geohash36/interface/rake/default.rb +28 -0
  15. data/lib/geohash36/interface/rake/documentation.rb +46 -0
  16. data/lib/geohash36/interface/rake/guard.rb +13 -0
  17. data/lib/geohash36/interface/rake/helpers.rb +27 -0
  18. data/lib/geohash36/interface/rake/library.rb +126 -0
  19. data/lib/geohash36/interface/rake/metric.rb +13 -0
  20. data/lib/geohash36/interface/rake/rspec.rb +8 -0
  21. data/lib/geohash36/interface/thor/info.thor +292 -0
  22. data/lib/geohash36/interface/thor/mixin/config_choice.rb +27 -0
  23. data/lib/geohash36/interface/thor/mixin/configuration.rb +28 -0
  24. data/lib/geohash36/interface/thor/mixin/default.rb +30 -0
  25. data/lib/geohash36/interface/thor/mixin/default_config.rb +31 -0
  26. data/lib/geohash36/interface/thor/mixin/guess.rb +57 -0
  27. data/lib/geohash36/interface/thor/mixin/logger.rb +43 -0
  28. data/lib/geohash36/interface/thor/mixin/shell.rb +225 -0
  29. data/lib/geohash36/interface/thor/version.thor +33 -0
  30. data/lib/geohash36/library/interval.rb +130 -0
  31. data/lib/geohash36/version.rb +13 -0
  32. data/lib/geohash36.rb +164 -0
  33. data/spec/geohash36_spec.rb +52 -0
  34. data/spec/library/interval_spec.rb +55 -0
  35. data/spec/spec_helper.rb +55 -0
  36. metadata +281 -0
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # System includes
5
+ require 'andand'
6
+ require 'ptools'
7
+ require 'tempfile'
8
+
9
+ # Custom includes
10
+ require File.expand_path( File.dirname( __FILE__ ) + '/guess' )
11
+
12
+
13
+ # @module module Mixin
14
+ # @brief Mixin module contains various functions to be used in other components
15
+ module Mixin
16
+
17
+ # @module Shell Module
18
+ # @brief Module wrapper around shell commands
19
+ module Shell
20
+
21
+ include ::Mixin::Guess
22
+
23
+ # @fn def initialize *args {{{
24
+ # @brief Default constructor
25
+ #
26
+ # @param [Array] args Argument array
27
+ def initialize *args
28
+ super
29
+ end # }}}
30
+
31
+ ## Actions
32
+
33
+ # @fn def run command {{{
34
+ # @brief Run the given command gracefully (without throwing exceptions)
35
+ #
36
+ # @param [String] command The command to run
37
+ # @param [RegExp] regexp Optional regular expression used for matching output
38
+ #
39
+ # @return [String] Returns empty string if command not found or other problem,
40
+ # otherwise result of command.
41
+ def run command, regexp = nil
42
+
43
+ result = ''
44
+
45
+ begin
46
+ if( regexp.nil? )
47
+ result = execute( command ).strip
48
+ else
49
+ raise ArgumentError, 'Regular Expression input needs to be of type Regexp' unless( regexp.is_a?( Regexp ) )
50
+
51
+ result = execute( command ).andand.send( :match, regexp ).andand.send( :to_s ).strip
52
+ end
53
+
54
+ rescue Exception => e
55
+ say '(EE) ' + e.message, :red
56
+ result = ''
57
+ end
58
+
59
+ return result
60
+ end # }}}
61
+
62
+ # @fn def execute command {{{
63
+ # @brief Execute single shell command
64
+ #
65
+ # @param [String] command Shell command string with arguments
66
+ #
67
+ # @return [String] Returns result of command
68
+ #
69
+ # @throws [ArgumentError] Throws exception if command not found
70
+ def execute command
71
+
72
+ exists = which( command )
73
+ raise ArgumentError, "Command not found" unless( exists )
74
+ result = `#{command}`
75
+
76
+ return result
77
+ end # }}}
78
+
79
+ # @fn def which command {{{
80
+ # @brief Checks if command is available
81
+ #
82
+ # @param [String] command Shell command string with or without arguments.
83
+ # If arguments are given, they are split on first
84
+ # whitespace and discarded
85
+ #
86
+ # @return [Boolean] Returns boolean true if command is available, false if not
87
+ #
88
+ #
89
+ # @info Crude alternative: `#{command} 2>/dev/null`.strip.empty?
90
+ def which command
91
+ result = false
92
+
93
+ begin
94
+ partial = command.to_s
95
+ partial = partial.split(' ').first.to_s if( partial =~ %r{ }i )
96
+ path = File.which( partial )
97
+
98
+ result = true unless( path.nil? )
99
+ rescue Exception => e
100
+ say "(EE) " + e.message, :red
101
+ result = false
102
+ end
103
+
104
+ return result
105
+ end # }}}
106
+
107
+ # @fn def version command {{{
108
+ # @brief Prints the version of given command, if command exists
109
+ #
110
+ # @param [String] command Command string to probe version for, e.g. ruby
111
+ #
112
+ # @return [String] Returns version string or empty if command not found / error
113
+ def version command
114
+
115
+ result = ""
116
+
117
+ begin
118
+
119
+ # Sanity
120
+ raise ArgumentError, "Command not found" unless( which( command ) )
121
+
122
+ # Get usage help screen for command
123
+ help = usage( command )
124
+
125
+ # Get version flag from help screen
126
+ flag = version_flag( help )
127
+
128
+ return result if( flag.empty? ) # some stupid commands don't follow standard rules, e.g. bundle
129
+
130
+ # Get actual version string
131
+ banner = run( command + " " + flag )
132
+
133
+ # Guess way to extract and extract semver
134
+ result = guess_version( banner.to_s )
135
+
136
+ rescue Exception => e
137
+ say "(EE) " + e.message, :red
138
+ result = ""
139
+ end
140
+
141
+ return result
142
+ end # }}}
143
+
144
+
145
+ alias_method :exists?, :which
146
+
147
+ private
148
+
149
+ # @fn def usage command {{{
150
+ # @brief Extracts help/usage screen from command
151
+ #
152
+ # @param [String] command Command string
153
+ #
154
+ # @return [String Result screen output string
155
+ def usage command
156
+
157
+ result = ""
158
+
159
+ begin
160
+
161
+ # Some commands misbehave when using wrong arguments
162
+ # e.g. java
163
+ help = []
164
+
165
+ # Collect all possible outputs
166
+ %w(--help -h -help).each do |argument|
167
+ tempfile = Tempfile.new( "geohash36-" )
168
+ `#{command} #{argument} > #{tempfile.path.to_s} 2>&1`
169
+ help << File.read( tempfile.path )
170
+ end
171
+
172
+ # Prune to relevent one
173
+ help.each do |h|
174
+
175
+ # Sanity
176
+ next if( h.strip.empty? )
177
+ next if( h.split( "\n" ).length < 4 )
178
+ next unless( h.match( /unknown/i ).to_s.empty? ) # does it contain unknown? (argument)
179
+ next unless( h.match( /unrecognized/i ).to_s.empty? ) # does it contain unrecognized? (argument)
180
+ next unless( h.match( /error/i ).to_s.empty? ) # does it contain error
181
+ next unless( h.match( /does not exist/i ).to_s.empty? ) # does not exist error
182
+ next unless( result.empty? )
183
+
184
+ result = h
185
+
186
+ end # of help.each
187
+
188
+
189
+ rescue Exception => e
190
+ say "(EE) " + e.message, :red
191
+ result = ""
192
+ end
193
+
194
+ return result
195
+ end # }}}
196
+
197
+ # @fn def version_flag usage {{{
198
+ # @brief Extracts version flag from usage help screen of command
199
+ #
200
+ # @param [String] usage Usage help screen output (string), e.g. ruby --help
201
+ #
202
+ # @return [String] Returns the string which according to help screen will print version
203
+ # e.g. -version for java
204
+ def version_flag usage
205
+
206
+ result = ""
207
+
208
+ begin
209
+ result = usage.match( /--version/i ).to_s
210
+ result = usage.match( /-version/i ).to_s if( result.empty? )
211
+ rescue Exception => e
212
+ say "(EE) " + e.message, :red
213
+ result = ""
214
+ end
215
+
216
+ return result
217
+ end # }}}
218
+
219
+ end # of Module Shell
220
+
221
+ end # of module Mixin
222
+
223
+
224
+
225
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # @class Server command class
5
+ # @brief Implements the server command
6
+ class Version < Thor
7
+
8
+ default_task :show
9
+
10
+ ## API
11
+
12
+ # @fn def show {{{
13
+ # @brief Show version string of app
14
+ desc 'show', 'Show version of this app'
15
+ def show
16
+ version = Geohash36::VERSION
17
+
18
+ puts version
19
+ end # }}}
20
+
21
+
22
+ private
23
+
24
+ no_tasks do
25
+
26
+ ## Actions
27
+
28
+ end # of no_tasks do
29
+
30
+ end # of Class Version
31
+
32
+
33
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,130 @@
1
+ # Designed to provide additional functionality for arrays
2
+ # to handle geographical intervals.
3
+ class Geohash36::Interval < Array
4
+
5
+ # @param array [Array<Fixnum, Float>] array with length 2.
6
+ # @param options [Hash]
7
+ # options affects borders in interval. By default, all borders are included.
8
+ # If you want to exclude left border, pass: `include_left: false`
9
+ # If you want to exclude right border, pass: `include_right: false`
10
+ # @example With default args
11
+ # Geohash36::Interval.new
12
+ # @example With array and options
13
+ # Geohash36::Interval.new([0, 6], include_right: false)
14
+ def initialize array = [0, 0], options = {}
15
+ array.try(:compact!)
16
+ validate_array(array)
17
+ array.each{|element| self.push element}
18
+ defaults = {include_right: true, include_left: true }
19
+ @opts = defaults.merge options
20
+ end
21
+
22
+ # Replace old interval options with new one
23
+ #
24
+ # @param options [Hash] new options for interval
25
+ def configure options = {}
26
+ @opts.merge! options
27
+ end
28
+
29
+ # Check if `number` between left and right border.
30
+ #
31
+ # @param number [Float, Fixmum] number to check
32
+ def include? number
33
+ for_left_border = (@opts[:include_left] == true) ? first <= number : first < number
34
+ for_right_number = (@opts[:include_right] == true) ? number <= last : number < last
35
+ for_left_border && for_right_number
36
+ end
37
+
38
+ # Split interval into 6 parts
39
+ # @return array of 6 intervals
40
+ def split
41
+ split3.each_with_object([]){|interval, result| result.concat interval.split2}
42
+ end
43
+
44
+ # Change values of interval
45
+ # @example
46
+ # my_interval = Geohash36::Interval.new([0, 1])
47
+ # my_interval.update [0,6]
48
+ # my_interval # => [0, 6]
49
+ def update array
50
+ array.try(:compact!)
51
+ validate_array(array)
52
+ self.clear
53
+ array.each{|element| self.push element}
54
+ end
55
+
56
+ # @return string representation of object
57
+ def inspect
58
+ left_br = @opts[:include_left] ? "[" : "("
59
+ right_br = @opts[:include_right] ? "]" : ")"
60
+ "#{left_br}#{first}, #{last}#{right_br}"
61
+ end
62
+
63
+ # @return string representation of object
64
+ def to_s
65
+ inspect
66
+ end
67
+
68
+ # @return middle of the interval
69
+ # @example
70
+ # Geohash36::Interval.new([0, 6]).middle
71
+ # # => 3.0
72
+ def middle
73
+ (first + last)/2.0
74
+ end
75
+
76
+ # @return third part of interval (only positive values)
77
+ # @example
78
+ # Geohash36::Interval.new([-2, 4]).third
79
+ # # => 2.0
80
+ def third
81
+ ((last - first)/3.0).abs
82
+ end
83
+
84
+ # Split interval into 2 parts
85
+ # @return array of 2 intervals
86
+ def split2
87
+ [[first, middle], [middle, last]].map{|interval| Geohash36::Interval.new interval}
88
+ end
89
+
90
+ # Split interval into 3 parts
91
+ # @return array of 3 intervals
92
+ def split3
93
+ result = [[self.first, self.first+third], [self.first+third, self.first+2*third], [self.first+2*third, self.last]]
94
+ result.map{|array| Geohash36::Interval.new array}
95
+ end
96
+
97
+ # Convert array of arrays to array of `Geohash36::Interval`s
98
+ #
99
+ # @param array [Array] array to convert
100
+ # @param options [Hash] options for `Geohash36::Interval` object
101
+ # but it works a little different. It is not affect first\last elements in array.
102
+ # For example, if we do not want to include left border, only first element
103
+ # will include left border because this class designed to handle geographical coordinates.
104
+ # It is not designed for abstract intervals.
105
+ # @example
106
+ # # for example, we don't want to include left border of interval,
107
+ # # so we will have array like `[[0, 0], [0, 0], [0, 0]] ->> [[0, 0], (0, 0], (0, 0]]`
108
+ #
109
+ # my_array = [[0, 2], [2, 6], [6, 10]]
110
+ # Geohash36.convert_array(my_array, include_left: false)
111
+ # # => [[0, 2], (2, 6], (6, 10]]
112
+ def self.convert_array array, options = {}
113
+ intervals = array.map{|interval| Geohash36::Interval.new interval, options }
114
+ intervals.first.configure(include_left: true) unless options[:include_left]
115
+ intervals.last.configure(include_right: true) unless options[:include_right]
116
+ intervals
117
+ end
118
+
119
+ private
120
+ # Check if array has valid values
121
+ def validate_array(array)
122
+ unless array.length == 2 && ( array.try(:first) <= array.try(:last) )
123
+ raise ArgumentError, "Not valid array for geohash interval"
124
+ end
125
+ end
126
+
127
+ end # of class Geohash36::Interval
128
+
129
+
130
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # @module Geohash36 Module
5
+ # @brief Implements the Geohash36 module wrapper around the Geohash36 API
6
+ class Geohash36
7
+
8
+ # Version of gem
9
+ VERSION = `git describe --tags`.split("-").first || "0.1.0"
10
+
11
+ end
12
+
13
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
data/lib/geohash36.rb ADDED
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # Standard includes
5
+ require 'bundler'
6
+ require 'thor'
7
+ require 'rake'
8
+ require 'ruby-try'
9
+
10
+ # Provides complete solution for geohashing
11
+ class Geohash36
12
+
13
+ # Geocode-36 matrix for map
14
+ GEOCODE_MATRIX = [
15
+ ['2', '3', '4', '5', '6', '7'],
16
+ ['8', '9', 'b', 'B', 'C', 'd'],
17
+ ['D', 'F', 'g', 'G', 'h', 'H'],
18
+ ['j', 'J', 'K', 'l', 'L', 'M'],
19
+ ['n', 'N', 'P', 'q', 'Q', 'r'],
20
+ ['R', 't', 'T', 'V', 'W', 'X']
21
+ ]
22
+ # Needed for inversion direction of latitude
23
+ GEOMATRIX_MAX_INDEX = 5
24
+ # Standart length of geocode
25
+ GEOCODE_LENGTH = 10
26
+ # Accuracy for coordinates when converting from geohash
27
+ DEFAULT_ACCURACY = 6
28
+
29
+ attr_reader :coords
30
+ attr_reader :hash
31
+ attr_accessor :accuracy
32
+
33
+ # Create new Geohash object from geohash or coordinates.
34
+ #
35
+ # @param object [Hash, String]
36
+ # @example Pass geohash
37
+ # Geohash36.new "l222222222222"
38
+ # @example Pass coordinates
39
+ # Geohash36.new latitude: 80, longitude: 20
40
+ def initialize(obj = { latitude: 0, longitude: 0 })
41
+ @accuracy = DEFAULT_ACCURACY
42
+ if obj.kind_of? Hash
43
+ Geohash36.validate_coords(obj)
44
+ @hash = Geohash36.to_geohash(obj)
45
+ @coords = obj
46
+ elsif obj.kind_of? String
47
+ Geohash36.validate_geohash(obj)
48
+ @hash = obj
49
+ @coords = Geohash36.to_coords(obj, @accuracy)
50
+ else
51
+ raise ArgumentError, "Argument type should be hash or string"
52
+ end
53
+ end
54
+
55
+ # Update geohash value. Coordinates will update automatically
56
+ def hash=(geohash)
57
+ raise ArgumenError unless geohash.kind_of? String
58
+ @hash = geohash
59
+ @coords = Geohash36.to_coords(geohash, @accuracy)
60
+ end
61
+
62
+ # Update coordinates values. Geohash will update automatically
63
+ def coords=(coords)
64
+ raise ArgumenError unless coords.kind_of? Hash
65
+ @hash = Geohash36.to_geohash(coords)
66
+ @coords.merge! coords
67
+ end
68
+
69
+
70
+ # Convert coordinates pair to geohash without creating an object
71
+ #
72
+ # @param coords [Hash] coordinates to convert
73
+ # @return [String] geohash
74
+ # @example
75
+ # Geohash36.to_geohash(latitude: 0, longitude: 0)
76
+ # # => "l222222222"
77
+ def self.to_geohash(coords)
78
+ Geohash36.validate_coords(coords)
79
+ lon_interval = Geohash36.basic_lon_interval
80
+ lat_interval = Geohash36.basic_lat_interval
81
+
82
+ (0...GEOCODE_LENGTH).map{Geohash36.geohash_symbol!(lon_interval, lat_interval, coords)}.join
83
+ end
84
+
85
+ # Convert geohash to coords without creating an object.
86
+ #
87
+ # @param [String] geohash
88
+ # @param accuracy [Fuxnum] accuracy for coordinates values
89
+ # @return [Hash] coordinates
90
+ # @example With default accuracy
91
+ # Geohash36.to_coords("l222222222")
92
+ # # => {:latitude=>-1.0e-06, :longitude=>3.0e-06}
93
+ # @example With accuracy 3
94
+ # Geohash36.to_coords("l222222222", 3)
95
+ # # => {:latitude=>0.0, :longitude=>0.0}
96
+ def self.to_coords(geohash, accuracy = DEFAULT_ACCURACY)
97
+ Geohash36.validate_geohash(geohash)
98
+
99
+ lon_interval = Geohash36.basic_lon_interval
100
+ lat_interval = Geohash36.basic_lat_interval
101
+
102
+ geohash.each_char do |c|
103
+ lon_intervals = Geohash36::Interval.convert_array(lon_interval.split)
104
+ lat_intervals = Geohash36::Interval.convert_array(lat_interval.split)
105
+
106
+ lat_index, lon_index = 0, 0
107
+
108
+ GEOCODE_MATRIX.each_with_index do |row, row_index|
109
+ if row.include? c
110
+ lat_index = GEOMATRIX_MAX_INDEX-row_index
111
+ lon_index = row.index(c)
112
+ break
113
+ end
114
+ end
115
+
116
+ lon_interval.update lon_intervals[lon_index]
117
+ lat_interval.update lat_intervals[lat_index]
118
+ end
119
+
120
+ { latitude: lat_interval.middle.round(accuracy) ,
121
+ longitude: lon_interval.middle.round(accuracy) }
122
+ end
123
+
124
+ private
125
+ def self.basic_lon_interval
126
+ Geohash36::Interval.new [-180, 180]
127
+ end
128
+
129
+ def self.basic_lat_interval
130
+ Geohash36::Interval.new [-90, 90]
131
+ end
132
+
133
+ def self.validate_geohash(geohash)
134
+ unless geohash =~ /\A[23456789bBCdDFgGhHjJKlLMnNPqQrRtTVWX]+{1,10}\z/
135
+ raise ArgumentError, "It is not Geohash-36."
136
+ end
137
+ end
138
+
139
+ def self.validate_coords(coords)
140
+ keys = coords.keys
141
+ raise ArgumentError, "Invalid hash" unless keys.length == 2 && keys.include?(:latitude) && keys.include?(:longitude)
142
+ lat_inclusion = Geohash36.basic_lat_interval.include? coords[:latitude]
143
+ lon_inclusion = Geohash36.basic_lon_interval.include? coords[:longitude]
144
+ raise ArgumentError, "Invalid hash values" unless lat_inclusion && lon_inclusion
145
+ end
146
+
147
+ def self.geohash_symbol!(lon_interval, lat_interval, coords)
148
+ lon_intervals = Geohash36::Interval.convert_array(lon_interval.split, include_right: false)
149
+ lat_intervals = Geohash36::Interval.convert_array(lat_interval.split, include_left: false)
150
+
151
+ lon_index = lon_intervals.index {|interval| interval.include? coords[:longitude] }
152
+ lat_index = lat_intervals.index {|interval| interval.include? coords[:latitude] }
153
+
154
+ lon_interval.update lon_intervals[lon_index]
155
+ lat_interval.update lat_intervals[lat_index]
156
+
157
+ GEOCODE_MATRIX[GEOMATRIX_MAX_INDEX-lat_index][lon_index]
158
+ end
159
+
160
+ end # of module Geohash36
161
+
162
+ Dir[File.dirname(__FILE__) + '/geohash36/library/*.rb'].each {|file| require file }
163
+
164
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # System include
4
+ require 'spec_helper'
5
+
6
+
7
+ describe Geohash36 do
8
+
9
+ it { expect{Geohash36.to_geohash(Hash.new)}.to raise_error(ArgumentError) }
10
+ it { expect{Geohash36.new 111 }.to raise_error(ArgumentError) }
11
+ it { expect{Geohash36.new Hash.new }.to raise_error(ArgumentError) }
12
+ it { expect{Geohash36.new "BB99999999"}.not_to raise_error }
13
+ it { expect{Geohash36.new latitude: 1, longitude: 2}.not_to raise_error }
14
+
15
+
16
+ context "when default args" do
17
+ context "coordinates" do
18
+ subject { Geohash36.new }
19
+
20
+ let(:default_coords) { {latitude: 0, longitude: 0} }
21
+ let(:default_hash) { 'l222222222' }
22
+ let(:some_coords) { {latitude: 54, longitude: 32} }
23
+ let(:some_hash) { 'BB99999999' }
24
+
25
+ its(:coords) { is_expected.to eq(default_coords)}
26
+ its(:hash) { is_expected.to eq(default_hash)}
27
+
28
+ it "should change coords when hash updated" do
29
+ expect{subject.hash = some_hash}.to change{subject.coords}
30
+ end
31
+
32
+ it "should change hash when coords updated" do
33
+ expect{subject.coords = some_coords}.to change{subject.hash}
34
+ end
35
+
36
+ it "should give appropriate hash for coords" do
37
+ subject.coords = some_coords
38
+ expect(subject.hash).to eq(some_hash)
39
+ end
40
+
41
+ it "should give appropriate coords for hash" do
42
+ subject.accuracy = 2
43
+ subject.hash = some_hash
44
+ expect(subject.coords).to eq(some_coords)
45
+ end
46
+
47
+ it { expect{subject.hash = ""}.to raise_error(ArgumentError) }
48
+ end # of context
49
+ end # of context
50
+ end # of describe
51
+
52
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Custom include
4
+ require 'spec_helper'
5
+
6
+ describe Geohash36::Interval do
7
+ it { expect{Geohash36::Interval.new [0]}.to raise_error(ArgumentError) }
8
+
9
+ context "[0, 6]" do
10
+ subject { Geohash36::Interval.new([0, 6]) }
11
+
12
+ its(:middle) { should == 3.0 }
13
+ its(:third) { should == 2.0 }
14
+ its(:split2) { should == [[0, 3.0], [3.0, 6]] }
15
+ its(:split3) { should == [[0, 2.0], [2.0, 4.0], [4.0, 6]] }
16
+ its(:split) { should == [[0, 1.0], [1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0], [5.0, 6]] }
17
+
18
+ context "when include all border" do
19
+ it { subject.to_s.should eq("[0, 6]")}
20
+ it { is_expected.to include?(0) }
21
+ it { is_expected.to include?(2) }
22
+ it { is_expected.to include?(6) }
23
+ it { is_expected.to_not include?(9) }
24
+ end
25
+
26
+ context "when not include right border" do
27
+ subject { Geohash36::Interval.new([0, 6], include_right: false) }
28
+
29
+ it { subject.to_s.should eq("[0, 6)")}
30
+ it { is_expected.to include?(0) }
31
+ it { is_expected.to include?(2) }
32
+ it { is_expected.to_not include?(6) }
33
+ it { is_expected.to_not include?(9) }
34
+ end
35
+
36
+ context "when not include left border" do
37
+ subject { Geohash36::Interval.new([0, 6], include_left: false) }
38
+
39
+ it { subject.to_s.should eq("(0, 6]")}
40
+ it { is_expected.to_not include?(0) }
41
+ it { is_expected.to include?(2) }
42
+ it { is_expected.to include?(6) }
43
+ it { is_expected.to_not include?(9) }
44
+ end
45
+
46
+ describe "#update" do
47
+ it "should properly update interval" do
48
+ expect{subject.update [1, 3]}.to change{subject}.to([1,3])
49
+ end
50
+ end
51
+
52
+ end # of context
53
+ end # of describe Geohash36::Interval
54
+
55
+ # vim:ts=2:tw=100:wm=100:syntax=ruby