slide_rule 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7118aaafe84fdcdf36f2186bfe731f935576e2d2
4
- data.tar.gz: e2aa86ba48acbaea385c76ee188e15795ce6fb7d
3
+ metadata.gz: d6f0cc115c650f57a1ebc32fb16dedb8647df5c4
4
+ data.tar.gz: cf1f0ba21b49a34ebc56d7595366180adec9d744
5
5
  SHA512:
6
- metadata.gz: f3892833589520f1ad3bbcfe83d1c4c18240cedc522ce45101d34a28cb7ba4e4ccb611f38e49a08cfba839b3ce750e63146d2286eea9d534b14554dcbed5deea
7
- data.tar.gz: 1d01a8617ac75abf8ef2d388472f243bb695924c0492ffbf358d4323d6b1b2c8af113dacd1ab92222ae036d7cc43871367f8c09bc6281cc1ca2e6b706434bc88
6
+ metadata.gz: 2fc5aff23287ff405bdc120e5378e48f3b10c30ef23bbd311766cf6cebd7b149dd0fcfc3a34e2fe94cbc45ffe0cbd8a5b6310f3e02031ead580922ff0ead0bba
7
+ data.tar.gz: e8913245a2286590fa8e8560885ce86024506fc132424813187103a71de0e625532cea53edc59c476038e3be29c46af6d009a03f3c7d605c31ae23022d861f15
data/.gitignore CHANGED
@@ -2,7 +2,3 @@
2
2
  **.DS_Store
3
3
  Guardfile
4
4
  Gemfile.lock
5
- vendor/cache
6
- .ruby-gemset
7
- .ruby-version
8
- pkg/
data/README.md CHANGED
@@ -19,26 +19,25 @@ _Note: weights are assumed to be equal if not provided_
19
19
 
20
20
  #API
21
21
 
22
- ##Describe the field distance calculators
22
+ ##Describe the field calculators
23
23
 
24
24
  Each field to be considered in the distance calculation should be described
25
25
  with a calculation method and weight(optional)
26
26
 
27
27
  Valid calculators:
28
28
 
29
- * day_of_year
30
- * day_of_month
31
- * levenshtein
29
+ * day_of_month (this needs to be factored into configurable date_recurrence)
30
+ * float_range_distance
32
31
 
33
32
  ```ruby
34
33
  distance_rules = {
35
34
  :description => {
36
35
  :weight => 0.80,
37
- :calculator => :levenshtein,
36
+ :type => :levenshtein,
38
37
  },
39
38
  :date => {
40
39
  :weight => 0.90,
41
- :calculator => :day_of_month,
40
+ :type => :day_of_month,
42
41
  },
43
42
  }
44
43
  ```
@@ -82,41 +81,3 @@ matcher.closest_match(candidate, [example, example2], 0.2)
82
81
  => example
83
82
 
84
83
  ```
85
-
86
- ## Custom Field Distance Calculators
87
-
88
- To define a custom field distance calculator, define a class with a `calculate(value1, value2)` method.
89
-
90
- Requirements:
91
- * Class must be stateless
92
- * Calculate should return a float from `0` (perfect match) to `1.0` (no match)
93
- * Calculation should not be order dependent (e.g. `calculate(a, b) == calculate(b, a)`)
94
-
95
- ```ruby
96
- class StringLengthCalculator
97
- def calculate(l1, l2)
98
- diff = (l1 - l2).abs.to_f
99
- return diff / [l1, l2].max
100
- end
101
- end
102
-
103
- matcher = ::SlideRule::DistanceCalculator.new(
104
- :length => {
105
- :weight => 1.0,
106
- :calculator => StringLengthCalculator
107
- }
108
- )
109
-
110
- # Find the string with the closest length
111
- matcher.closest_match("Howdy Doody Time!", ["Felix the cat", "Mighty Mouse"], 0.5)
112
- # => { :item=>"Mighty Mouse", :distance=>0.29411764705882354 }
113
- ```
114
-
115
- See the [distance_calculators](https://github.com/mattnichols/slide_rule/tree/master/lib/slide_rule/distance_calculators) directory in source for more examples.
116
-
117
-
118
- # To Do
119
-
120
- * Add more field distance calculators
121
-
122
-
@@ -1,9 +1,7 @@
1
1
  module SlideRule
2
2
  class DistanceCalculator
3
- attr_accessor :rules
4
-
5
3
  def initialize(rules)
6
- @rules = prepare_rules(rules)
4
+ @rules = normalize_weights(rules)
7
5
  end
8
6
 
9
7
  # TODO: Figure this out. Very inefficient!
@@ -22,21 +20,19 @@ module SlideRule
22
20
  end
23
21
  end
24
22
 
25
- def closest_match(obj, array, threshold = 1.0)
26
- matches(obj, array, threshold).sort_by { |match| match[:distance] }.first
23
+ def closest_match(obj, array, threshold)
24
+ matches(obj, array, threshold).sort { |match| match[:distance] }.first
27
25
  end
28
26
 
29
- def closest_matching_item(obj, array, threshold = 1.0)
30
- match = closest_match(obj, array, threshold)
31
- return nil if match.nil?
32
-
33
- match[:item]
27
+ def is_match?(obj_1, obj_2, threshold)
28
+ distance = calculate_distance(obj_1, obj_2)
29
+ distance < threshold
34
30
  end
35
31
 
36
32
  def matches(obj, array, threshold)
37
33
  array.map do |item|
38
34
  distance = calculate_distance(obj, item)
39
- next nil unless distance <= threshold
35
+ next nil unless distance < threshold
40
36
  {
41
37
  item: item,
42
38
  distance: distance
@@ -52,40 +48,23 @@ module SlideRule
52
48
  # {
53
49
  # :attribute_name => {
54
50
  # :weight => 0.90,
55
- # :calculator => :distance_calculator,
51
+ # :type => :distance_calculator,
56
52
  # }
57
53
  # }
58
54
  def calculate_distance(i1, i2)
59
- calculate_weighted_distances(i1, i2).reduce(0.0) do |distance, obj|
60
- distance + (obj[:distance] * obj[:weight])
61
- end
62
- end
63
-
64
- private
65
-
66
- def calculate_weighted_distances(i1, i2)
67
- distances = @rules.map do |attribute, rule|
55
+ @rules.map do |attribute, rule|
68
56
  val1 = i1.send(attribute)
69
57
  val2 = i2.send(attribute)
70
- distance = rule[:calculator].calculate(val1, val2)
71
- next { distance: distance.to_f, weight: rule[:weight] } unless distance.nil?
72
-
73
- nil
74
- end
75
- normalize_weights_array(distances) if distances.compact!
76
-
77
- distances
58
+ calculator = get_calculator(rule[:type])
59
+ calculator.calculate(val1, val2).to_f * rule[:weight]
60
+ end.reduce(0.0, &:+)
78
61
  end
79
62
 
80
63
  def get_calculator(calculator)
81
64
  return calculator.new if calculator.is_a?(Class)
82
65
 
83
66
  klass_name = "#{calculator.to_s.split('_').collect(&:capitalize).join}"
84
- klass = begin
85
- ::SlideRule::DistanceCalculators.const_get(klass_name)
86
- rescue(::NameError)
87
- nil
88
- end
67
+ klass = ::SlideRule::DistanceCalculators.const_get(klass_name)
89
68
 
90
69
  fail ArgumentError, "Unable to find calculator #{klass_name}" if klass.nil?
91
70
 
@@ -94,46 +73,12 @@ module SlideRule
94
73
 
95
74
  # Ensures all weights add up to 1.0
96
75
  #
97
- def normalize_weights(rules)
76
+ def normalize_weights(rules_hash)
77
+ rules = rules_hash.dup
98
78
  weight_total = rules.map { |_attr, rule| rule[:weight] }.reduce(0.0, &:+)
99
79
  rules.each do |_attr, rule|
100
80
  rule[:weight] = rule[:weight] / weight_total
101
81
  end
102
82
  end
103
-
104
- # Ensures all weights add up to 1.0 in array of hashes
105
- #
106
- def normalize_weights_array(rules)
107
- weight_total = rules.map { |rule| rule[:weight] }.reduce(0.0, &:+)
108
- rules.each do |rule|
109
- rule[:weight] = rule[:weight] / weight_total
110
- end
111
- end
112
-
113
- # Prepares a duplicate of given rules hash with normalized weights and calculator instances
114
- #
115
- def prepare_rules(rules)
116
- prepared_rules = rules.each_with_object({}) do |(attribute, rule), copy|
117
- rule = copy[attribute] = safe_dup(rule)
118
-
119
- if rule[:type]
120
- puts 'Rule key `:type` is deprecated. Use `:calculator` instead.'
121
- rule[:calculator] = rule[:type]
122
- end
123
-
124
- rule[:calculator] = get_calculator(rule[:calculator])
125
-
126
- copy
127
- end
128
- prepared_rules = normalize_weights(prepared_rules)
129
-
130
- prepared_rules
131
- end
132
-
133
- def safe_dup(obj)
134
- obj.dup
135
- rescue
136
- obj
137
- end
138
83
  end
139
84
  end
@@ -23,7 +23,6 @@ module SlideRule
23
23
  private
24
24
 
25
25
  def cleanse_date(date)
26
- date = Time.at(date).utc.to_date if date.is_a?(::Fixnum)
27
26
  date = Date.parse(date) unless date.is_a?(::Date) || date.is_a?(::Time)
28
27
  date = date.to_date if date.is_a?(::Time)
29
28
 
@@ -18,7 +18,6 @@ module SlideRule
18
18
  private
19
19
 
20
20
  def cleanse_date(date)
21
- date = Time.at(date).utc.to_date if date.is_a?(::Fixnum)
22
21
  date = Date.parse(date) unless date.is_a?(::Date) || date.is_a?(::Time)
23
22
  date = date.to_date if date.is_a?(::Time)
24
23
 
@@ -1,3 +1,3 @@
1
1
  module SlideRule
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -19,12 +19,6 @@ describe ::SlideRule::DistanceCalculator do
19
19
  end
20
20
  end
21
21
 
22
- class NilCalc
23
- def calculate(_first, _second)
24
- nil
25
- end
26
- end
27
-
28
22
  let(:examples) do
29
23
  [
30
24
  ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com'),
@@ -42,31 +36,50 @@ describe ::SlideRule::DistanceCalculator do
42
36
  ::SlideRule::DistanceCalculator.new(
43
37
  description: {
44
38
  weight: 0.80,
45
- calculator: :levenshtein
39
+ type: :levenshtein
46
40
  },
47
41
  date: {
48
42
  weight: 0.90,
49
- calculator: :day_of_month
43
+ type: :day_of_month
50
44
  }
51
45
  )
52
46
  end
53
47
 
54
- it 'finds closest' do
48
+ it 'finds recurring transaction' do
55
49
  example = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
56
50
  expect(calculator.closest_match(example, examples, 0.2)[:item]).to eq(examples[3])
57
51
 
58
52
  example = ExampleTransaction.new(description: 'Audible.com', date: '2015-06-05')
59
53
  expect(calculator.closest_match(example, examples, 0.2)[:item]).to eq(examples[0])
60
54
  end
55
+ end
61
56
 
62
- it 'with default threshold' do
63
- example = ExampleTransaction.new(description: 'Audible.com', date: '2015-06-05')
64
- expect(calculator.closest_match(example, examples)[:item]).to eq(examples[0])
57
+ describe '#is_match?' do
58
+ let(:calculator) do
59
+ ::SlideRule::DistanceCalculator.new(
60
+ description: {
61
+ weight: 0.80,
62
+ type: :levenshtein
63
+ },
64
+ date: {
65
+ weight: 0.90,
66
+ type: :day_of_month
67
+ }
68
+ )
65
69
  end
66
70
 
67
- it 'finds closest matching item' do
68
- example = ExampleTransaction.new(description: 'Audible.com', date: '2015-06-05')
69
- expect(calculator.closest_matching_item(example, examples)).to eq(examples[0])
71
+ it 'returns true if there is a match' do
72
+ example_1 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
73
+ example_2 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
74
+
75
+ expect(calculator.is_match?(example_1, example_2, 0.2)).to be(true)
76
+ end
77
+
78
+ it 'returns false if there is a match' do
79
+ example_1 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
80
+ example_2 = ExampleTransaction.new(description: 'Taco Bell', date: '2015-06-17')
81
+
82
+ expect(calculator.is_match?(example_1, example_2, 0.2)).to be(false)
70
83
  end
71
84
  end
72
85
 
@@ -76,11 +89,11 @@ describe ::SlideRule::DistanceCalculator do
76
89
  calculator = ::SlideRule::DistanceCalculator.new(
77
90
  description: {
78
91
  weight: 1.00,
79
- calculator: :levenshtein
92
+ type: :levenshtein
80
93
  },
81
94
  date: {
82
95
  weight: 0.50,
83
- calculator: :day_of_month
96
+ type: :day_of_month
84
97
  }
85
98
  )
86
99
  example = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
@@ -92,11 +105,11 @@ describe ::SlideRule::DistanceCalculator do
92
105
  calculator = ::SlideRule::DistanceCalculator.new(
93
106
  description: {
94
107
  weight: 0.50,
95
- calculator: :levenshtein
108
+ type: :levenshtein
96
109
  },
97
110
  date: {
98
111
  weight: 0.50,
99
- calculator: :day_of_month
112
+ type: :day_of_month
100
113
  }
101
114
  )
102
115
  example = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
@@ -112,23 +125,6 @@ describe ::SlideRule::DistanceCalculator do
112
125
  distance = calculator.calculate_distance(example, candidate)
113
126
  expect(distance.round(4)).to eq(((3.0 * 0.5 / 15) + (4.0 * 0.5 / 11)).round(4))
114
127
  end
115
-
116
- it 'should renormalize on nil' do
117
- calculator = ::SlideRule::DistanceCalculator.new(
118
- description: {
119
- weight: 0.50,
120
- calculator: :levenshtein
121
- },
122
- date: {
123
- weight: 0.50,
124
- calculator: NilCalc
125
- }
126
- )
127
- example1 = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
128
- example2 = ::ExampleTransaction.new(amount: 25.00, date: '2015-06-08', description: 'Audible Inc')
129
-
130
- expect(calculator.calculate_distance(example1, example2).round(4)).to eq((4.0 / 11).round(4))
131
- end
132
128
  end
133
129
 
134
130
  context 'uses custom calculator' do
@@ -136,7 +132,7 @@ describe ::SlideRule::DistanceCalculator do
136
132
  calculator = ::SlideRule::DistanceCalculator.new(
137
133
  description: {
138
134
  weight: 1.00,
139
- calculator: CustomCalc
135
+ type: CustomCalc
140
136
  }
141
137
  )
142
138
  example = ::ExampleTransaction.new
@@ -146,51 +142,5 @@ describe ::SlideRule::DistanceCalculator do
146
142
  expect(distance).to eq(0.9)
147
143
  end
148
144
  end
149
-
150
- describe '#initialize' do
151
- context 'validates rules on initialize' do
152
- it 'should allow :type' do
153
- ::SlideRule::DistanceCalculator.new(
154
- description: {
155
- weight: 1.00,
156
- type: CustomCalc
157
- }
158
- )
159
- end
160
-
161
- it 'should not modify input rule hash' do
162
- rules = {
163
- description: {
164
- weight: 1.0,
165
- calculator: CustomCalc
166
- },
167
- name: {
168
- weight: 1.0,
169
- type: CustomCalc
170
- }
171
- }
172
- ::SlideRule::DistanceCalculator.new(rules)
173
- # Run a second time to ensure that no calculator instance is in rules. Will currently throw an error.
174
- ::SlideRule::DistanceCalculator.new(rules)
175
-
176
- # :type should still be in original hash
177
- expect(rules[:name].key?(:calculator)).to eq(false)
178
-
179
- # :weight should not be normalized in original hash
180
- expect(rules[:name][:weight]).to eq(1.0)
181
- end
182
-
183
- it 'should raise error if not valid calculator' do
184
- expect do
185
- ::SlideRule::DistanceCalculator.new(
186
- description: {
187
- weight: 1.00,
188
- calculator: :some_junk
189
- }
190
- )
191
- end.to raise_error(::ArgumentError, 'Unable to find calculator SomeJunk')
192
- end
193
- end
194
- end
195
145
  end
196
146
  end
@@ -6,10 +6,6 @@ describe ::SlideRule::DistanceCalculators::DayOfMonth do
6
6
  expect(described_class.new.calculate('2012-03-19', '2014-08-19')).to eq(0.0)
7
7
  end
8
8
 
9
- it 'should accept epoch date' do
10
- expect(described_class.new.calculate(1_444_262_400, 1_444_262_400)).to eq(0.0)
11
- end
12
-
13
9
  it 'should calculate when date is in the same month' do
14
10
  expect(described_class.new.calculate('2012-03-19', '2014-08-22')).to eq(3.0 / 15)
15
11
  expect(described_class.new.calculate('2012-03-19', '2014-08-09')).to eq(10.0 / 15)
@@ -5,10 +5,6 @@ describe ::SlideRule::DistanceCalculators::DayOfYear do
5
5
  it 'should return a 0 distance' do
6
6
  expect(described_class.new.calculate('2015-10-8', '2015-10-8')).to eq(0.0)
7
7
  end
8
-
9
- it 'should accept epoch date' do
10
- expect(described_class.new.calculate(1_444_262_400, 1_444_262_400)).to eq(0.0)
11
- end
12
8
  end
13
9
 
14
10
  context 'when dates are more than a year apart' do
@@ -1,19 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ::SlideRule::DistanceCalculators::Levenshtein do
4
- let(:subject) { described_class.new }
5
-
6
4
  it 'should calculate perfect match' do
7
- expect(subject.calculate('this is a test', 'this is a test')).to eq(0.0)
5
+ expect(described_class.new.calculate('this is a test', 'this is a test')).to eq(0.0)
8
6
  end
9
7
 
10
8
  it 'should calculate distance as distance divided by length of longest string' do
11
- expect(subject.calculate('this is a test', 'this is a test!').round(4)).to eq((1.0 / 15).round(4))
12
- end
13
-
14
- it 'should handle nils' do
15
- expect(subject.calculate(nil, nil)).to eq(0.0)
16
- expect(subject.calculate(nil, 'goodbye')).to eq(1.0)
17
- expect(subject.calculate('hello', nil)).to eq(1.0)
9
+ expect(described_class.new.calculate('this is a test', 'this is a test!').round(4)).to eq((1.0 / 15).round(4))
18
10
  end
19
11
  end
data/spec/spec_helper.rb CHANGED
@@ -18,7 +18,6 @@
18
18
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
19
 
20
20
  require_relative '../lib/slide_rule.rb'
21
- require 'pry'
22
21
 
23
22
  RSpec.configure do |config|
24
23
  # rspec-expectations config goes here. You can use an alternate
metadata CHANGED
@@ -1,97 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slide_rule
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mattnichols
8
8
  - fergmastaflex
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-20 00:00:00.000000000 Z
12
+ date: 2016-01-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: vladlev
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - "~>"
17
+ - - ~>
19
18
  - !ruby/object:Gem::Version
20
19
  version: '1.0'
21
- type: :runtime
20
+ name: vladlev
22
21
  prerelease: false
22
+ type: :runtime
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ~>
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.0'
28
28
  - !ruby/object:Gem::Dependency
29
- name: rake
30
29
  requirement: !ruby/object:Gem::Requirement
31
30
  requirements:
32
- - - "~>"
31
+ - - ~>
33
32
  - !ruby/object:Gem::Version
34
33
  version: '10'
35
- type: :development
34
+ name: rake
36
35
  prerelease: false
36
+ type: :development
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ~>
40
40
  - !ruby/object:Gem::Version
41
41
  version: '10'
42
42
  - !ruby/object:Gem::Dependency
43
- name: pry
44
43
  requirement: !ruby/object:Gem::Requirement
45
44
  requirements:
46
- - - "~>"
45
+ - - ~>
47
46
  - !ruby/object:Gem::Version
48
47
  version: '0'
49
- type: :development
48
+ name: pry
50
49
  prerelease: false
50
+ type: :development
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
- name: rspec
58
57
  requirement: !ruby/object:Gem::Requirement
59
58
  requirements:
60
- - - "~>"
59
+ - - ~>
61
60
  - !ruby/object:Gem::Version
62
61
  version: '3'
63
- type: :development
62
+ name: rspec
64
63
  prerelease: false
64
+ type: :development
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - "~>"
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
69
  version: '3'
70
70
  - !ruby/object:Gem::Dependency
71
- name: rubocop
72
71
  requirement: !ruby/object:Gem::Requirement
73
72
  requirements:
74
- - - "~>"
73
+ - - ~>
75
74
  - !ruby/object:Gem::Version
76
75
  version: '0'
77
- type: :development
76
+ name: rubocop
78
77
  prerelease: false
78
+ type: :development
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - "~>"
81
+ - - ~>
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
- description: Calculates the distance between 2 arbitrary objects using specified fields
85
- and algorithms.
84
+ description: Calculates the distance between 2 arbitrary objects using specified fields and algorithms.
86
85
  email:
87
86
  - dev@mx.com
88
87
  executables: []
89
88
  extensions: []
90
89
  extra_rdoc_files: []
91
90
  files:
92
- - ".gitignore"
93
- - ".rubocop.yml"
94
- - ".travis.yml"
91
+ - .gitignore
92
+ - .rubocop.yml
93
+ - .travis.yml
95
94
  - CODE_OF_CONDUCT.md
96
95
  - Gemfile
97
96
  - LICENSE
@@ -113,24 +112,24 @@ homepage: https://github.com/mattnichols/slide_rule
113
112
  licenses:
114
113
  - MIT
115
114
  metadata: {}
116
- post_install_message:
115
+ post_install_message:
117
116
  rdoc_options: []
118
117
  require_paths:
119
118
  - lib
120
119
  required_ruby_version: !ruby/object:Gem::Requirement
121
120
  requirements:
122
- - - ">="
121
+ - - '>='
123
122
  - !ruby/object:Gem::Version
124
123
  version: '0'
125
124
  required_rubygems_version: !ruby/object:Gem::Requirement
126
125
  requirements:
127
- - - ">="
126
+ - - '>='
128
127
  - !ruby/object:Gem::Version
129
128
  version: '0'
130
129
  requirements: []
131
- rubyforge_project:
132
- rubygems_version: 2.4.6
133
- signing_key:
130
+ rubyforge_project:
131
+ rubygems_version: 2.4.8
132
+ signing_key:
134
133
  specification_version: 4
135
134
  summary: Ruby object distance calculator
136
135
  test_files: