geohash36 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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