ruleby 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,18 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
1
12
  $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
2
13
  require 'ruleby'
3
- require 'rulebook'
14
+
15
+ include Ruleby
4
16
 
5
17
  class Message
6
18
  def initialize(status,message)
@@ -13,33 +25,19 @@ end
13
25
 
14
26
  class HelloWorldRulebook < Rulebook
15
27
  def rules
16
- rule 'HelloWorld' do |r|
17
- r.when do |has|
18
- has.m Message
19
- has.m.status = :HELLO
20
- end
21
- r.then = action do |e,vars|
22
- puts vars[:m].message
23
- e.retract vars[:m]
24
- vars[:m].message = "Goodbye world"
25
- vars[:m].status = :GOODBYE
26
- e.assert vars[:m]
27
- end
28
+ rule [Message, :m, m.status == :HELLO] do |e,v|
29
+ puts v[:m].message
30
+ v[:m].message = "Goodbye world"
31
+ v[:m].status = :GOODBYE
32
+ e.modify v[:m]
28
33
  end
29
34
 
30
- rule 'Goodbye' do |r|
31
- r.when do |has|
32
- has.m Message
33
- has.m.status = :GOODBYE
34
- end
35
- r.then = action do |e,vars|
36
- puts vars[:m].message
37
- end
35
+ rule [Message, :m, m.status == :GOODBYE] do |e,v|
36
+ puts v[:m].message
38
37
  end
39
38
  end
40
39
  end
41
40
 
42
- include Ruleby
43
41
 
44
42
  engine :engine do |e|
45
43
  HelloWorldRulebook.new(e).rules
@@ -1,6 +1,18 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
1
12
  $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
2
13
  require 'ruleby'
3
- require 'rulebook'
14
+
15
+ include Ruleby
4
16
 
5
17
  class Politician
6
18
  def initialize(name,honest)
@@ -16,23 +28,24 @@ end
16
28
  class Hope
17
29
  end
18
30
 
31
+ # NOTE this example demonstrates the BlueSteel (block based) DSL syntax
19
32
  class PoliticianRulebook < Rulebook
20
- def rules
21
- rule 'We have an honest Politician' do |r|
33
+ def rules
34
+ rule :We_have_an_honest_Politician do |r|
22
35
  r.when do |has|
23
36
  has.p Politician
24
37
  has.p.honest = true
25
38
  end
26
- r.then = action do |e,vars|
39
+ r.then do |e,vars|
27
40
  e.assert Hope.new
28
41
  end
29
42
  end
30
43
 
31
- rule 'Hope Lives' do |r|
44
+ rule :Hope_Lives do |r|
32
45
  r.when do |has|
33
46
  has.h Hope
34
47
  end
35
- r.then = action do |e,vars|
48
+ r.then do |e,vars|
36
49
  puts 'Hurrah!!! Democracy Lives'
37
50
  end
38
51
  r.priority = 10
@@ -46,20 +59,20 @@ class PoliticianRulebook < Rulebook
46
59
  # r.when = pattern do |p|
47
60
  # p.not :h, Hope
48
61
  # end
49
- # r.then = action 'Hope is Dead' do |r,vars|
62
+ # r.then 'Hope is Dead' do |r,vars|
50
63
  # puts 'We are all Doomed!!! Democracy is Dead'
51
64
  # end
52
65
  # r.priority = -1
53
66
  # end
54
67
 
55
- rule 'Corrupt the Honest' do |r|
68
+ rule :Corrupt_the_Honest do |r|
56
69
  r.when do |has|
57
70
  has.p Politician
58
71
  has.p.honest = true
59
72
 
60
73
  has.h Hope
61
74
  end
62
- r.then = action do |e,vars|
75
+ r.then do |e,vars|
63
76
  puts 'I am an evil corporation and I have corrupted ' + vars[:p].name
64
77
  vars[:p].honest = false
65
78
  e.modify vars[:p]
@@ -69,8 +82,6 @@ class PoliticianRulebook < Rulebook
69
82
  end
70
83
  end
71
84
 
72
- include Ruleby
73
-
74
85
  p1 = Politician.new('blair', true)
75
86
  p2 = Politician.new('bush', true)
76
87
  p3 = Politician.new('chirac', true)
@@ -1,11 +1,18 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
1
12
  $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
2
13
  require 'ruleby'
3
- require 'rulebook'
4
14
 
5
- # NOTE : before we can get this example working we need to figure out exactly
6
- # what the conflict resolution strategy should be. When we implement the
7
- # default strategy as we understand it (from various literature) this example
8
- # does not work (nor should it). But this example works in drools as is. Why?
15
+ include Ruleby
9
16
 
10
17
  class Customer
11
18
  def initialize(name,subscription)
@@ -21,7 +28,7 @@ end
21
28
  class Ticket
22
29
  def initialize(customer)
23
30
  @customer = customer
24
- @status = 'New'
31
+ @status = :New
25
32
  end
26
33
  attr :status, true
27
34
  attr_reader :customer
@@ -31,107 +38,55 @@ class Ticket
31
38
  end
32
39
 
33
40
  # This example is used in JBoss-Rules to demonstrate durations and the use of
34
- # custom DSL. We are simply using here to demonstrate another example.
41
+ # custom DSL. We are simply using it here to demonstrate another example.
35
42
  class TroubleTicketRulebook < Rulebook
36
43
  def rules
37
- rule 'New Ticket' do |r|
38
- r.when do |has|
39
- has.customer Customer
40
- has.ticket Ticket
41
- has.ticket.customer = :customer, :%
42
- has.ticket.status = 'New'
43
- end
44
-
45
- r.then = action do |e,vars|
44
+
45
+ # This is uses the letigre syntax... but we can mix and match syntaxes in
46
+ # the same rule set.
47
+ rule :New_Ticket, {:priority => 10}, # :duration => 10},
48
+ 'Customer as :c',
49
+ 'Ticket as :ticket where #customer == #:c #&& #status == :New' do |e,vars|
46
50
  puts 'New : ' + vars[:ticket].to_s
47
- end
48
-
49
- r.priority = 10
50
- #r.duration = 10
51
51
  end
52
52
 
53
- rule 'Silver Priority' do |r|
54
- r.when do |has|
55
- has.customer Customer
56
- has.customer.subscription = 'Silver'
57
-
58
- has.ticket Ticket
59
- has.ticket.customer = :customer, :%
60
- has.ticket.status = 'New'
61
- end
62
-
63
- r.then = action do |e,vars|
64
- vars[:ticket].status = 'Escalate'
53
+ # Now we are using the ferrari syntax. The rule method can detect which
54
+ # syntax we are using, and compile accordingly.
55
+ rule :Silver_Priority, #{:duration => 3000},
56
+ [Customer, :customer, m.subscription == 'Silver'],
57
+ [Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
58
+ vars[:ticket].status = :Escalate
65
59
  e.modify vars[:ticket]
66
- end
67
- #r.duration = 3000
68
60
  end
69
61
 
70
- rule 'Gold Priority' do |r|
71
- r.when do |has|
72
- has.customer Customer
73
- has.customer.subscription = 'Gold'
74
-
75
- has.ticket Ticket
76
- has.ticket.customer = :customer, :%
77
- has.ticket.status = 'New'
78
- end
79
-
80
- r.then = action do |e,vars|
81
- vars[:ticket].status = 'Escalate'
62
+ rule :Gold_Priority, #{:duration => 1000},
63
+ [Customer, :customer, m.subscription == 'Gold'],
64
+ [Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
65
+ vars[:ticket].status = :Escalate
82
66
  e.modify vars[:ticket]
83
- end
84
- #r.duration = 1000
85
67
  end
86
68
 
87
- rule 'Platinum Priority' do |r|
88
- r.when do |has|
89
- has.customer Customer
90
- has.customer.subscription = 'Platinum'
91
-
92
- has.ticket Ticket
93
- has.ticket.customer = :customer, :%
94
- has.ticket.status = 'New'
95
- end
96
-
97
- r.then = action do |e,vars|
98
- vars[:ticket].status = 'Escalate'
69
+ rule :Platinum_Priority,
70
+ [Customer, :customer, m.subscription == 'Platinum'],
71
+ [Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
72
+ vars[:ticket].status = :Escalate
99
73
  e.modify vars[:ticket]
100
- end
101
74
  end
102
75
 
103
- rule 'Escalate' do |r|
104
- r.when do |has|
105
- has.customer Customer
106
-
107
- has.ticket Ticket
108
- has.ticket.customer = :customer, :%
109
- has.ticket.status = 'Escalate'
110
- end
111
-
112
- r.then = action do |e,vars|
76
+ rule :Escalate,
77
+ 'Customer as :c',
78
+ 'Ticket as :ticket where #customer == #:c #&& #status == :Escalate' do |e,vars|
113
79
  puts 'Email : ' + vars[:ticket].to_s
114
- end
115
80
  end
116
81
 
117
- rule 'Done' do |r|
118
- r.when do |has|
119
- has.customer Customer
120
-
121
- has.ticket Ticket
122
- has.ticket.customer = :customer, :%
123
- has.ticket.status = 'Done'
124
- end
125
-
126
- r.then = action do |e,vars|
82
+ rule :Done,
83
+ 'Customer as :c',
84
+ 'Ticket as :ticket where #customer == #:c #&& #status == :Done' do |e,vars|
127
85
  puts 'Done : ' + vars[:ticket].to_s
128
- end
129
86
  end
130
87
  end
131
88
  end
132
89
 
133
- include Ruleby
134
-
135
90
  # FACTS
136
91
 
137
92
  a = Customer.new('A', 'Gold')
@@ -1,3 +1,14 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
1
12
  $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
2
13
  require 'ruleby'
3
14
  require 'fibonacci_rulebook'
@@ -20,11 +31,11 @@ include Ruleby
20
31
  # This example is borrowed from the JBoss-Rule project.
21
32
 
22
33
  # FACTS
23
- fib1 = Fibonacci.new(8)
34
+ fib1 = Fibonacci.new(150)
24
35
 
25
36
  t1 = Time.new
26
37
  engine :engine do |e|
27
- FibonacciRulebook1.new(e).rules
38
+ FibonacciRulebookFerrari.new(e).rules
28
39
  e.assert fib1
29
40
  e.match
30
41
  end
@@ -1,3 +1,14 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
1
12
  $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
2
13
  require 'ruleby'
3
14
  require 'fibonacci_rulebook'
@@ -1,26 +1,27 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
1
11
 
2
- require 'rulebook'
12
+ require 'ruleby'
13
+
14
+ include Ruleby
15
+
16
+ # NOTE this example uses the LeTigre DSL syntax. In addition, its semantics are
17
+ # different from the other classes.
3
18
  class FibonacciRulebook2 < Rulebook
4
19
  MAX_SEQUENCE = 100
5
20
  def rules
6
- rule 'Calculate' do |r|
7
-
8
- r.when do |has|
9
- has.f1 Fibonacci
10
- has.f1.value.not = -1
11
- has.f1.sequence :s1
12
-
13
- has.f2 Fibonacci
14
- has.f2.value.not = -1
15
- has.f2.sequence :s2
16
- has.f2.sequence :s1 do |s, s1| s == (s1 + 1) end
17
-
18
- has.f3 Fibonacci
19
- has.f3.value = -1
20
- has.f3.sequence :s2 do |s, s2| s == (s2 + 1) end
21
- end
22
-
23
- r.then do |e, vars|
21
+ rule :Calculate, {:priority => 2 },
22
+ 'Fibonacci as :f1 where #value != -1 #&& #sequence as :s1',
23
+ 'Fibonacci as :f2 where #value != -1 #&& #sequence == #:s1 + 1 as :s2',
24
+ 'Fibonacci as :f3 where #value == -1 #&& #sequence == #:s2 + 1' do |e, vars|
24
25
  e.retract vars[:f1]
25
26
  e.retract vars[:f3]
26
27
  if(vars[:f2].sequence == MAX_SEQUENCE)
@@ -29,109 +30,55 @@ class FibonacciRulebook2 < Rulebook
29
30
  f3 = Fibonacci.new(vars[:f2].sequence + 1, vars[:f1].value + vars[:f2].value)
30
31
  e.assert f3
31
32
  puts "#{f3.sequence} == #{f3.value}"
32
- end
33
- end
34
-
35
- r.priority = 2
33
+ end
36
34
  end
37
35
 
38
- rule 'Build' do |r|
39
-
40
- r.when do |has|
41
- has.f Fibonacci
42
- has.f.value.not = -1
43
- has.f.sequence :s1
44
-
45
- has.f2 Fibonacci
46
- has.f2.value.not = -1
47
- has.f2.sequence :s1 do |s, s1| s == (s1 + 1) end
48
- end
49
-
50
- r.then do |e, vars|
36
+ rule :Build, {:priority => 1},
37
+ 'Fibonacci as :f1 where #value != -1 #&& #sequence as :s1',
38
+ 'Fibonacci as :f2 where #value != -1 #&& #sequence == #:s1 + 1' do |e, vars|
51
39
  f3 = Fibonacci.new(vars[:f2].sequence + 1, -1)
52
40
  e.assert f3
53
- end
54
-
55
- r.priority = 1
56
41
  end
57
42
  end
58
43
  end
59
44
 
60
- class FibonacciRulebook1 < Rulebook
61
-
45
+ # NOTE
46
+ # In this class we demonstrate the Ferrari DSL syntax.
47
+ class FibonacciRulebookFerrari < Rulebook
62
48
  def rules
63
49
  # Bootstrap1
64
- rule 'Bootstrap1' do |r|
65
- r.when do |has|
66
- has.f Fibonacci
67
- has.f.value = -1
68
- has.f.sequence = 1
69
- end
70
-
71
- r.then do |e,vars|
72
- vars[:f].value = 1
73
- e.modify vars[:f]
74
- puts vars[:f].sequence.to_s + ' == ' + vars[:f].value.to_s
75
- end
76
-
77
- r.priority = 4
78
- end
50
+ rule :Bootstrap1, {:priority => 4},
51
+ [Fibonacci, :f, m.value == -1, m.sequence == 1 ] do |e,vars|
52
+ vars[:f].value = 1
53
+ e.modify vars[:f]
54
+ puts vars[:f].sequence.to_s + ' == ' + vars[:f].value.to_s
55
+ end
79
56
 
80
- # Recurse
81
- rule 'Recurse' do |r|
82
- r.when do |has|
83
- has.f Fibonacci
84
- has.f.value = -1
85
- end
86
-
87
- r.then do |e,vars|
88
- f2 = Fibonacci.new(vars[:f].sequence - 1)
89
- e.assert f2
90
- puts 'recurse for ' + f2.sequence.to_s
91
- end
92
- r.priority = 3
93
- end
57
+ # Recurse
58
+ rule :Recurse, {:priority => 3},
59
+ [Fibonacci, :f, m.value == -1] do |e,vars|
60
+ f2 = Fibonacci.new(vars[:f].sequence - 1)
61
+ e.assert f2
62
+ puts 'recurse for ' + f2.sequence.to_s
63
+ end
94
64
 
95
- # Bootstrap2
96
- rule 'Bootstrap2' do |r|
97
- r.when do |has|
98
- has.f9 Fibonacci
99
- has.f9.value = -1
100
- has.f9.sequence = 2
101
- end
102
- r.then do |e,vars|
103
- vars[:f9].value = 1
104
- e.modify vars[:f9]
105
- puts vars[:f9].sequence.to_s + ' == ' + vars[:f9].value.to_s
106
- end
107
- r.priority = 0
108
- end
65
+ # Bootstrap2
66
+ rule :Bootstrap2,
67
+ [Fibonacci, :f, m.value == -1 , m.sequence == 2] do |e,vars|
68
+ vars[:f].value = 1
69
+ e.modify vars[:f]
70
+ puts vars[:f].sequence.to_s + ' == ' + vars[:f].value.to_s
71
+ end
109
72
 
110
- # Calculate
111
- rule 'Calculate' do |r|
112
- r.when do |has|
113
- has.f1 Fibonacci
114
- has.f1.value.not = -1
115
- has.f1.sequence :s1
116
-
117
- has.f2 Fibonacci
118
- has.f2.value.not = -1
119
- has.f2.sequence :s2
120
- has.f2.sequence.references :s1
121
- has.f2.sequence do |s2, s1| s2 == (s1 + 1) end
122
-
123
- has.f3 Fibonacci
124
- has.f3.value = -1
125
- has.f3.sequence.references :s2
126
- has.f3.sequence do |sequence, s2| sequence == (s2 + 1) end
73
+ # Calculate
74
+ rule :Calculate,
75
+ [Fibonacci,:f1, m.value.not== -1, {m.sequence => :s1}],
76
+ [Fibonacci,:f2, m.value.not== -1, {m.sequence( :s1, &c{ |s2,s1| s2 == s1 + 1 } ) => :s2}],
77
+ [Fibonacci,:f3, m.value == -1, m.sequence(:s2, &c{ |s3,s2| s3 == s2 + 1 }) ] do |e,vars|
78
+ vars[:f3].value = vars[:f1].value + vars[:f2].value
79
+ e.modify vars[:f3]
80
+ e.retract vars[:f1]
81
+ puts vars[:f3].sequence.to_s + ' == ' + vars[:f3].value.to_s
127
82
  end
128
- r.then do |e,vars|
129
- vars[:f3].value = vars[:f1].value + vars[:f2].value
130
- e.modify vars[:f3]
131
- e.retract vars[:f1]
132
- puts vars[:f3].sequence.to_s + ' == ' + vars[:f3].value.to_s
133
- end
134
- r.priority = 0
135
- end
136
- end
137
- end
83
+ end
84
+ end