heuristics 1.0.1 → 1.0.2

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