heuristics 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -41,6 +41,9 @@ Or install it yourself as:
41
41
 
42
42
  ## Usage
43
43
 
44
+ **NOTE**: Order matters. First assumption to return true for all conditions will be used.
45
+ This means you should write your assumptions in the order from most specific to least specfic.
46
+
44
47
  # Creates a new heuristic named :field_tester
45
48
  Heuristics.define(:field_tester) do
46
49
 
@@ -67,10 +70,19 @@ Or install it yourself as:
67
70
  # Returns :hash_with_values in this case
68
71
  Heuristics.test(:field_tester, {a: 1})
69
72
 
73
+ **Test an array of value** (Also shows of using heuristic without a name):
74
+ Heuristics.define do
75
+
76
+ # Default value to return if no assumptions match
77
+ assume_default :set
78
+
79
+ assume(:date) { condition { Chronic.parse(value) != nil } }
80
+ assume(:string) { condition { value.instance_of? String } } }
81
+ assume(:integer) { condition { value.instance_of? Fixnum } }}
82
+ end
70
83
 
71
- NOTE:
72
- Order matters. First assumption to return true for all conditions will be used.
73
- This means you should write your assumptions in the order from most specific to least specfic.
84
+ Heuristics.test([1,2,3,'23.09.85','1','2','3','4']) # returns :string
85
+
74
86
 
75
87
  ## Contributing
76
88
 
data/lib/heuristics.rb CHANGED
@@ -8,12 +8,12 @@ module Heuristics
8
8
  class << self
9
9
  @@testers = {}
10
10
 
11
- def define(name, &block)
11
+ def define(name = :default, &block)
12
12
  raise "A heuristic with the name '#{name}' already exists" unless @@testers[name].nil?
13
13
  @@testers[name] = Tester.new(Docile.dsl_eval(Builder.new, &block))
14
14
  end
15
15
 
16
- def test(name, value)
16
+ def test(value, name = :default)
17
17
  unless @@testers.key? name
18
18
  raise "Heuristic named #{name} hasn't been defined."
19
19
  else
@@ -5,7 +5,28 @@ module Heuristics
5
5
  end
6
6
 
7
7
  def test(value)
8
- @builder.tests.map{|k, e| e.check(value) ? k : nil }.reject(&:nil?).first || @builder.default
8
+ freq = Frequency.new
9
+ [*value].map do |v|
10
+ freq.add(@builder.tests.map{|k, e| e.check(v) ? k : nil }.reject(&:nil?).first || @builder.default)
11
+ end
12
+
13
+ freq.list.keys.first
14
+ end
15
+
16
+ private
17
+ class Frequency
18
+ def initialize()
19
+ @storage = {}
20
+ end
21
+
22
+ def add(name)
23
+ @storage[name] ||= 0
24
+ @storage[name] += 1
25
+ end
26
+
27
+ def list
28
+ Hash[@storage.sort_by{|key, value| value }.reverse]
29
+ end
9
30
  end
10
31
  end
11
32
  end
@@ -1,3 +1,3 @@
1
1
  module Heuristics
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -1,36 +1,15 @@
1
1
  require_relative '../../test_helper'
2
2
 
3
3
  describe Heuristics do
4
- before do
5
- # @default = Heuristics.define do
6
- #
7
- # assume_default :string
8
- #
9
- # assume :integer do
10
- # condition { value =~ /\A\d+\Z/ }
11
- # end
12
- #
13
- # assume :email do
14
- # condition { value =~ /\A.*@.*\Z/}
15
- # end
16
- #
17
- # assume :date_of_birth do
18
- # require 'chronic'
19
- #
20
- # condition { Chronic.parse(value) }
21
- # end
22
- #
23
- # assume :phone_number do
24
- # condition { value.starts_with? '+353' } and
25
- # condition { value.scan(/\d/).length > 5 }
26
- # end
27
- # end
4
+ it 'should allow skipping the heuristics name' do
5
+ Heuristics.define { assume_default :string; assume(:email) { condition { false } } }
6
+ Heuristics.test(1).must_equal :string
28
7
  end
29
8
 
30
9
  it 'should allow to use external libs for testing' do
31
10
  require 'chronic'
32
11
  Heuristics.define(:external_lib_test) { assume(:date) { condition { Chronic.parse(value) != nil } } }
33
- Heuristics.test(:external_lib_test, '23.09.85').must_equal :date
12
+ Heuristics.test('23.09.85', :external_lib_test).must_equal :date
34
13
  end
35
14
 
36
15
  it 'should return the assumption that first matched all conditions' do
@@ -43,19 +22,19 @@ describe Heuristics do
43
22
  assume(:string) { condition { value.instance_of? String } }
44
23
  end
45
24
 
46
- Heuristics.test(:first_come_first_serve, '23.09.85').must_equal :date
47
- Heuristics.test(:first_come_first_serve, '27').must_equal :integer_string
48
- Heuristics.test(:first_come_first_serve, 'This is string').must_equal :string
25
+ Heuristics.test('23.09.85', :first_come_first_serve).must_equal :date
26
+ Heuristics.test('27', :first_come_first_serve).must_equal :integer_string
27
+ Heuristics.test('This is string', :first_come_first_serve).must_equal :string
49
28
  end
50
29
 
51
30
  it 'should return default if no assumptions are true' do
52
31
  Heuristics.define(:default_test) { assume_default :string; assume(:email) { condition { false } } }
53
- Heuristics.test(:default_test, 1).must_equal :string
32
+ Heuristics.test(1, :default_test).must_equal :string
54
33
  end
55
34
 
56
35
  it 'should return nil if no default is set' do
57
36
  Heuristics.define(:default_test2) { assume(:nothing) { condition { false } } }
58
- Heuristics.test(:default_test2, 1).must_be :nil?
37
+ Heuristics.test(1, :default_test2).must_be :nil?
59
38
  end
60
39
 
61
40
  it 'should return the first true assumption' do
@@ -64,12 +43,25 @@ describe Heuristics do
64
43
  assume(:string) { condition { value.instance_of? String } }
65
44
  assume(:hash) { condition { value.instance_of? String } }
66
45
  end
67
- Heuristics.test(:assumption_test, 'abc').must_equal :string
46
+ Heuristics.test('abc', :assumption_test).must_equal :string
68
47
  end
69
48
 
70
49
  it 'should support complex types' do
71
50
  Heuristics.define(:complex_test) { assume_default :integer; assume(:test) { condition { value[:hepp] } } }
72
- Heuristics.test(:complex_test, []).must_equal :integer
51
+ Heuristics.test(Object.new, :complex_test).must_equal :integer
52
+ end
53
+
54
+ it 'should determine the most frequent type of an array' do
55
+ require 'chronic'
56
+
57
+ Heuristics.define(:array_test) do
58
+ assume(:date) { condition { Chronic.parse(value) } }
59
+ assume(:string) { condition { value.instance_of? String } }
60
+ assume(:integer) { condition { value.instance_of? Fixnum } }
61
+ end
62
+
63
+ Heuristics.test([1,2,3,'a','b','c','d'], :array_test).must_equal :string
64
+ Heuristics.test([1,2,'a','b','c','23.09.85','23.09.85','23.09.85','23.09.85'], :array_test).must_equal :date
73
65
  end
74
66
 
75
67
  it 'should raise an exception if trying to create a heuristic with a name that already exists ' do
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: heuristics
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.1
5
+ version: 1.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Peter Haza
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-22 00:00:00.000000000 Z
12
+ date: 2013-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  version_requirements: !ruby/object:Gem::Requirement