ruleby 0.2 → 0.3

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.
@@ -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