ruleby 0.9.b4 → 0.9.b7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +5 -0
  2. data/GPL.txt +341 -0
  3. data/LICENSE.txt +52 -0
  4. data/README.markdown +22 -0
  5. data/benchmarks/basic_rules.rb +61 -0
  6. data/benchmarks/joined_rules.rb +66 -0
  7. data/benchmarks/miss_manners/data.rb +146 -0
  8. data/benchmarks/miss_manners/miss_manners.rb +33 -0
  9. data/benchmarks/miss_manners/model.rb +193 -0
  10. data/benchmarks/miss_manners/rules.rb +105 -0
  11. data/benchmarks/model.rb +36 -0
  12. data/examples/diagnosis.rb +129 -0
  13. data/examples/fibonacci_example1.rb +44 -0
  14. data/examples/fibonacci_example2.rb +40 -0
  15. data/examples/fibonacci_example3.rb +78 -0
  16. data/examples/fibonacci_rulebook.rb +84 -0
  17. data/examples/hello.rb +45 -0
  18. data/examples/ticket.rb +113 -0
  19. data/examples/wordgame.rb +107 -0
  20. data/lib/core/engine.rb +26 -24
  21. data/lib/core/nodes.rb +77 -35
  22. data/lib/ruleby.rb +0 -37
  23. data/ruleby.gemspec +17 -0
  24. data/spec/and_or_spec.rb +252 -0
  25. data/spec/coercion_spec.rb +5 -0
  26. data/spec/collect_spec.rb +1021 -0
  27. data/spec/errors_spec.rb +148 -0
  28. data/spec/ferrari_spec.rb +39 -0
  29. data/spec/function_spec.rb +199 -0
  30. data/spec/hello_spec.rb +34 -0
  31. data/spec/node_sharing_spec.rb +53 -0
  32. data/spec/property_spec.rb +69 -0
  33. data/spec/spec.opts +4 -0
  34. data/spec/spec_helper.rb +9 -0
  35. data/tasks/documentation.rake +32 -0
  36. data/tasks/rspec.rake +21 -0
  37. data/tasks/test.rake +9 -0
  38. data/tests/assert_facts.rb +130 -0
  39. data/tests/common.rb +29 -0
  40. data/tests/duck_type.rb +79 -0
  41. data/tests/gets.rb +48 -0
  42. data/tests/join_nodes.rb +63 -0
  43. data/tests/nil.rb +72 -0
  44. data/tests/not_patterns.rb +91 -0
  45. data/tests/or_patterns.rb +154 -0
  46. data/tests/regex.rb +47 -0
  47. data/tests/self_reference.rb +54 -0
  48. metadata +81 -49
@@ -0,0 +1,66 @@
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
+
12
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
13
+ require 'ruleby'
14
+ require 'model'
15
+
16
+ include Ruleby
17
+
18
+ class TestRulebook < Rulebook
19
+ def rules(n)
20
+ (1..n).each do |index|
21
+ rule "Rule-#{index}".to_sym,
22
+ [Account, :acc,
23
+ method.status == 'standard',
24
+ {method.account_id => :id}
25
+ ],
26
+ [Address, :addr,
27
+ method.addr_id == b(:id),
28
+ method.city == 'Foobar',
29
+ method.state == 'FB',
30
+ method.zip == '12345'],
31
+ &lambda {|vars| }
32
+ end
33
+ end
34
+ end
35
+
36
+ def run_benchmark(rules,facts)
37
+ puts "running benchmark for: #{rules} rules and #{facts} facts"
38
+
39
+ t1 = Time.new
40
+ engine :engine do |e|
41
+ TestRulebook.new(e).rules(rules)
42
+
43
+ t2 = Time.new
44
+ diff = t2.to_f - t1.to_f
45
+ puts 'time to create rule set: ' + diff.to_s
46
+ #e.print
47
+ for k in (1..facts)
48
+ e.assert Account.new('standard', nil, "acc#{k}")
49
+ e.assert Address.new("acc#{k}",'Foobar', 'FB', '12345')
50
+ end
51
+ #exit(0)
52
+ t3 = Time.new
53
+ diff = t3.to_f - t2.to_f
54
+ puts 'time to assert facts: ' + diff.to_s
55
+
56
+ e.match
57
+
58
+ t4 = Time.new
59
+ diff = t4.to_f - t3.to_f
60
+ puts 'time to run agenda: ' + diff.to_s
61
+ end
62
+ end
63
+
64
+ run_benchmark(5, 50)
65
+ puts '-------'
66
+ run_benchmark(50, 50)
@@ -0,0 +1,146 @@
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
+
12
+ module MissManners
13
+ class MannersData
14
+ def initialize
15
+ @guests16 = [
16
+ Guest.new(:n1, :f, :h3),
17
+ Guest.new(:n1, :f, :h1),
18
+ Guest.new(:n1, :f, :h2),
19
+ Guest.new(:n2, :f, :h3),
20
+ Guest.new(:n2, :f, :h2),
21
+ Guest.new(:n3, :m, :h1),
22
+ Guest.new(:n3, :m, :h3),
23
+ Guest.new(:n4, :m, :h2),
24
+ Guest.new(:n4, :m, :h1),
25
+ Guest.new(:n5, :m, :h2),
26
+ Guest.new(:n5, :m, :h3),
27
+ Guest.new(:n6, :m, :h2),
28
+ Guest.new(:n6, :m, :h1),
29
+ Guest.new(:n7, :f, :h2),
30
+ Guest.new(:n7, :f, :h1),
31
+ Guest.new(:n7, :f, :h3),
32
+ Guest.new(:n8, :f, :h3),
33
+ Guest.new(:n8, :f, :h2),
34
+ Guest.new(:n9, :f, :h1),
35
+ Guest.new(:n9, :f, :h3),
36
+ Guest.new(:n9, :f, :h2),
37
+ Guest.new(:n10, :m, :h2),
38
+ Guest.new(:n10, :m, :h3),
39
+ Guest.new(:n11, :m, :h3),
40
+ Guest.new(:n11, :m, :h2),
41
+ Guest.new(:n11, :m, :h1),
42
+ Guest.new(:n12, :m, :h3),
43
+ Guest.new(:n12, :m, :h1),
44
+ Guest.new(:n13, :m, :h2),
45
+ Guest.new(:n13, :m, :h3),
46
+ Guest.new(:n13, :m, :h1),
47
+ Guest.new(:n14, :f, :h3),
48
+ Guest.new(:n14, :f, :h1),
49
+ Guest.new(:n15, :f, :h3),
50
+ Guest.new(:n15, :f, :h2),
51
+ Guest.new(:n15, :f, :h1),
52
+ Guest.new(:n16, :f, :h3),
53
+ Guest.new(:n16, :f, :h2),
54
+ Guest.new(:n16, :f, :h1),
55
+ LastSeat.new(16)]
56
+
57
+ @guests32 = [
58
+ Guest.new(:n1, :m, :h1),
59
+ Guest.new(:n1, :m, :h3),
60
+ Guest.new(:n2, :f, :h3),
61
+ Guest.new(:n2, :f, :h2),
62
+ Guest.new(:n2, :f, :h1),
63
+ Guest.new(:n3, :f, :h1),
64
+ Guest.new(:n3, :f, :h2),
65
+ Guest.new(:n4, :f, :h3),
66
+ Guest.new(:n4, :f, :h1),
67
+ Guest.new(:n5, :f, :h1),
68
+ Guest.new(:n5, :f, :h2),
69
+ Guest.new(:n6, :m, :h1),
70
+ Guest.new(:n6, :m, :h2),
71
+ Guest.new(:n6, :m, :h3),
72
+ Guest.new(:n7, :f, :h2),
73
+ Guest.new(:n7, :f, :h1),
74
+ Guest.new(:n7, :f, :h3),
75
+ Guest.new(:n8, :f, :h1),
76
+ Guest.new(:n8, :f, :h3),
77
+ Guest.new(:n8, :f, :h2),
78
+ Guest.new(:n9, :f, :h1),
79
+ Guest.new(:n9, :f, :h3),
80
+ Guest.new(:n9, :f, :h2),
81
+ Guest.new(:n10, :m, :h2),
82
+ Guest.new(:n10, :m, :h1),
83
+ Guest.new(:n11, :m, :h2),
84
+ Guest.new(:n11, :m, :h1),
85
+ Guest.new(:n12, :m, :h3),
86
+ Guest.new(:n12, :m, :h2),
87
+ Guest.new(:n13, :m, :h1),
88
+ Guest.new(:n13, :m, :h3),
89
+ Guest.new(:n14, :m, :h3),
90
+ Guest.new(:n14, :m, :h2),
91
+ Guest.new(:n15, :f, :h2),
92
+ Guest.new(:n15, :f, :h1),
93
+ Guest.new(:n15, :f, :h3),
94
+ Guest.new(:n16, :f, :h3),
95
+ Guest.new(:n16, :f, :h2),
96
+ Guest.new(:n16, :f, :h1),
97
+ Guest.new(:n17, :m, :h3),
98
+ Guest.new(:n17, :m, :h2),
99
+ Guest.new(:n18, :f, :h2),
100
+ Guest.new(:n18, :f, :h1),
101
+ Guest.new(:n19, :f, :h1),
102
+ Guest.new(:n19, :f, :h2),
103
+ Guest.new(:n19, :f, :h3),
104
+ Guest.new(:n20, :f, :h1),
105
+ Guest.new(:n20, :f, :h2),
106
+ Guest.new(:n20, :f, :h3),
107
+ Guest.new(:n21, :m, :h2),
108
+ Guest.new(:n21, :m, :h3),
109
+ Guest.new(:n21, :m, :h1),
110
+ Guest.new(:n22, :f, :h1),
111
+ Guest.new(:n22, :f, :h2),
112
+ Guest.new(:n22, :f, :h3),
113
+ Guest.new(:n23, :f, :h3),
114
+ Guest.new(:n23, :f, :h1),
115
+ Guest.new(:n23, :f, :h2),
116
+ Guest.new(:n24, :m, :h1),
117
+ Guest.new(:n24, :m, :h3),
118
+ Guest.new(:n25, :f, :h3),
119
+ Guest.new(:n25, :f, :h2),
120
+ Guest.new(:n25, :f, :h1),
121
+ Guest.new(:n26, :f, :h3),
122
+ Guest.new(:n26, :f, :h2),
123
+ Guest.new(:n26, :f, :h1),
124
+ Guest.new(:n27, :m, :h3),
125
+ Guest.new(:n27, :m, :h1),
126
+ Guest.new(:n27, :m, :h2),
127
+ Guest.new(:n28, :m, :h3),
128
+ Guest.new(:n28, :m, :h1),
129
+ Guest.new(:n29, :m, :h3),
130
+ Guest.new(:n29, :m, :h2),
131
+ Guest.new(:n29, :m, :h1),
132
+ Guest.new(:n30, :m, :h2),
133
+ Guest.new(:n30, :m, :h1),
134
+ Guest.new(:n30, :m, :h3),
135
+ Guest.new(:n31, :m, :h2),
136
+ Guest.new(:n31, :m, :h1),
137
+ Guest.new(:n32, :m, :h1),
138
+ Guest.new(:n32, :m, :h3),
139
+ Guest.new(:n32, :m, :h2),
140
+ LastSeat.new(32)]
141
+ end
142
+
143
+ attr_reader :guests16
144
+ attr_reader :guests32
145
+ end
146
+ end
@@ -0,0 +1,33 @@
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
+
12
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../../lib/')
13
+ require 'ruleby'
14
+ require 'model'
15
+ require 'data'
16
+ require 'rules'
17
+
18
+ include Ruleby
19
+ include MissManners
20
+
21
+ t1 = Time.new
22
+ engine :e do |e|
23
+ MannersRulebook.new(e).rules
24
+ MannersData.new.guests16.each do |g|
25
+ e.assert g
26
+ end
27
+ e.assert Context.new(:start)
28
+ e.assert Count.new(1)
29
+ e.match
30
+ end
31
+ t2 = Time.new
32
+ diff = t2.to_f - t1.to_f
33
+ puts diff.to_s
@@ -0,0 +1,193 @@
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
+
12
+ module MissManners
13
+
14
+ class Chosen
15
+ def initialize(id,guestName,hobby)
16
+ @id = id
17
+ @guestName = guestName
18
+ @hobby = hobby
19
+ end
20
+ attr_reader :id, :guestName, :hobby
21
+ def to_s
22
+ "{Chosen id=#{@id}, name=#{@guestName}, hobbies=#{@hobby}}"
23
+ end
24
+ end
25
+
26
+ class Context
27
+ START_UP = 0
28
+ ASSIGN_SEATS = 1
29
+ MAKE_PATH = 2
30
+ CHECK_DONE = 3
31
+ PRINT_RESULTS = 4
32
+ STATE_STRINGS = ["START_UP","ASSIGN_SEATS","MAKE_PATH","CHECK_DONE","PRINT_RESULTS"]
33
+ def initialize(state)
34
+ if state == :start
35
+ @state = START_UP
36
+ else
37
+ raise "Context #{state.to_s} does not exist for Context Enum"
38
+ end
39
+ end
40
+ attr :state, true
41
+ def string_value
42
+ return STATE_STRINGS[@state]
43
+ end
44
+ def is_state(state)
45
+ return @state == state
46
+ end
47
+ def to_s
48
+ return "[Context state=" + string_value.to_s + "]";
49
+ end
50
+ end
51
+
52
+ class Count
53
+ def initialize(value)
54
+ @value = value
55
+ end
56
+ attr :value, true
57
+ def ==(object)
58
+ if object.object_id == self.object_id
59
+ return true
60
+ elsif object == nil || !(object.kind_of?(Count))
61
+ return false
62
+ end
63
+ return @value == object.value;
64
+ end
65
+ def to_s
66
+ return "[Count value=#{@value.to_s}]"
67
+ end
68
+ def to_hash
69
+ return value.to_hash
70
+ end
71
+ end
72
+
73
+ class Guest
74
+ def initialize(name,sex,hobby)
75
+ @name = name
76
+ @sex = sex
77
+ @hobby = hobby
78
+ end
79
+ attr_reader :name,:sex,:hobby
80
+ def to_s
81
+ return "[Guest name=" + @name.to_s + ", sex=" + @sex.to_s + ", hobbies=" + @hobby.to_s + "]";
82
+ end
83
+ end
84
+
85
+ class Hobby
86
+ @stringH1 = "h1"
87
+ @stringH2 = "h2"
88
+ @stringH3 = "h3"
89
+ @stringH4 = "h4"
90
+ @stringH5 = "h5"
91
+ HOBBY_STRINGS = [@stringH1,@stringH2,@stringH3,@stringH4,@stringH5]
92
+ def initialize(hobby)
93
+ @hobbyIndex = hobby-1
94
+ @hobby = HOBBY_STRINGS[@hobbyIndex]
95
+ end
96
+ H1 = Hobby.new(1)
97
+ H2 = Hobby.new(2)
98
+ H3 = Hobby.new(3)
99
+ H4 = Hobby.new(4)
100
+ H5 = Hobby.new(5)
101
+ attr_reader :hobby
102
+ def resolve(hobby)
103
+ if @stringH1 == hobby
104
+ return H1
105
+ elsif @stringH2 == hobby
106
+ return H2
107
+ elsif @stringH3 == hobby
108
+ return H3
109
+ elsif @stringH4 == hobby
110
+ return H4
111
+ elsif @stringH5 == hobby
112
+ return H5
113
+ else
114
+ raise "Hobby '" + @hobby.to_s + "' does not exist for Hobby Enum"
115
+ end
116
+ end
117
+ def to_hash
118
+ return @hobbyIndex.to_hash
119
+ end
120
+ def to_s
121
+ return @hobby
122
+ end
123
+ end
124
+
125
+ class LastSeat
126
+ def initialize(seat)
127
+ @seat = seat
128
+ end
129
+ attr_reader :seat
130
+ def to_s
131
+ return "[LastSeat seat=#{@seat.to_s}]"
132
+ end
133
+ end
134
+
135
+ class Path
136
+ def initialize(id,seat,guestName)
137
+ @id = id
138
+ @guestName = guestName
139
+ @seat = seat
140
+ end
141
+ attr_reader :id, :guestName, :seat
142
+ def to_s
143
+ "[Path id=#{@id.to_s}, name=#{@guestName.to_s}, seat=#{@seat.to_s}]"
144
+ end
145
+ end
146
+
147
+ class Seating
148
+ def initialize(id,pid,path,leftSeat,leftGuestName,rightSeat,rightGuestName)
149
+ @id = id
150
+ @pid = pid
151
+ @path = path
152
+ @leftSeat = leftSeat
153
+ @leftGuestName = leftGuestName
154
+ @rightSeat = rightSeat
155
+ @rightGuestName = rightGuestName
156
+ end
157
+ attr :path, true
158
+ attr_reader :id,:pid,:leftSeat,:leftGuestName,:rightSeat,:rightGuestName
159
+ def to_s
160
+ return "[Seating id=#{@id.to_s} , pid=#{pid.to_s} , pathDone=#{@path.to_s} , leftSeat=#{@leftSeat.to_s}, leftGuestName=#{@leftGuestName.to_s}, rightSeat=#{@rightSeat.to_s}, rightGuestName=#{@rightGuestName.to_s}]";
161
+ end
162
+ end
163
+
164
+ class Sex
165
+ STRING_M = 'm'
166
+ STRING_F = 'f'
167
+ SEX_LIST = [ STRING_M, STRING_F ]
168
+ def initialize(sex)
169
+ @sex = sex
170
+ end
171
+ M = Sex.new( 0 )
172
+ F = Sex.new( 1 )
173
+ def sex
174
+ return SEX_LIST[sex]
175
+ end
176
+ def resolve(sex)
177
+ if STRING_M == sex
178
+ return M
179
+ elsif STRING_F == sex
180
+ return F
181
+ else
182
+ raise "Sex '#{@sex.to_s}' does not exist for Sex Enum"
183
+ end
184
+ end
185
+ def to_s
186
+ return @sex.to_s
187
+ end
188
+ def to_hash
189
+ return @sex.to_hash
190
+ end
191
+ end
192
+
193
+ end
@@ -0,0 +1,105 @@
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
+
12
+ require 'model'
13
+
14
+ module MissManners
15
+
16
+ class MannersRulebook < Ruleby::Rulebook
17
+ def rules
18
+ rule :assignFirstSeat,
19
+ [Context,:context, m.state == Context::START_UP],
20
+ [Guest,:guest],
21
+ [Count,:count] do |vars|
22
+ guestName = vars[:guest].name
23
+ seating = Seating.new(vars[:count].value,1,true,1,guestName,1,guestName)
24
+ assert seating
25
+ path = Path.new(vars[:count].value, 1, guestName)
26
+ assert path
27
+ retract vars[:count]
28
+ vars[:count].value = vars[:count].value + 1
29
+ assert vars[:count]
30
+ puts "assign first seat : #{seating.to_s} : #{path.to_s}"
31
+ vars[:context].state = Context::ASSIGN_SEATS
32
+ modify vars[:context]
33
+ end
34
+
35
+ rule :findSeating,
36
+ [Context,:context, {m.state == Context::ASSIGN_SEATS => :state}],
37
+ [Count,:count, {m.value => :countValue}],
38
+ [Seating,:seating, {m.path == true =>:p, m.id=>:seatingId, m.pid=>:seatingPid, m.rightSeat=>:seatingRightSeat, m.rightGuestName=>:seatingRightGuestName}],
39
+ [Guest,:g, {m.name=>:name, m.sex=>:rightGuestSex, m.hobby=>:rightGuestHobby}, m.name == b(:seatingRightGuestName)],
40
+ [Guest,:lg, {m.name=>:leftGuestName, m.sex=>:sex, m.hobby == b(:rightGuestHobby) => :hobby}, m.sex(:rightGuestSex, &c{|s,rgs| s != rgs} )],
41
+ [:~,Path, m.id == b(:seatingId), m.guestName == b(:leftGuestName)],
42
+ [:~,Chosen, m.id == b(:seatingId), m.guestName == b(:leftGuestName), m.hobby == b(:leftGuestHobby)] do |vars|
43
+ rightSeat = vars[:seatingRightSeat]
44
+ seatId = vars[:seatingId]
45
+ countValue = vars[:count].value
46
+ seating = Seating.new(countValue,seatId,false,rightSeat,vars[:seatingRightGuestName],rightSeat+1,vars[:leftGuestName])
47
+ path = Path.new(countValue,rightSeat+1,vars[:leftGuestName])
48
+ chosen = Chosen.new(seatId, vars[:leftGuestName], vars[:rightGuestHobby] )
49
+ puts "find seating : #{seating} : #{path} : #{chosen}"
50
+ assert seating
51
+ assert path
52
+ assert chosen
53
+ vars[:count].value = countValue + 1
54
+ modify vars[:count]
55
+ vars[:context].state = Context::MAKE_PATH
56
+ modify vars[:context]
57
+ end
58
+
59
+ rule :makePath,
60
+ [Context,:context, {m.state == Context::MAKE_PATH => :s}],
61
+ [Seating,:seating, {m.id=>:seatingId, m.pid=>:seatingPid, m.path == false =>:p}],
62
+ [Path,:path, {m.guestName=>:pathGuestName, m.seat=>:pathSeat}, m.id == b(:seatingPid)],
63
+ [:~,Path,m.id == b(:seatingId), m.guestName == b(:pathGuestName)] do |vars|
64
+ path = Path.new(vars[:seatingId],vars[:pathSeat],vars[:pathGuestName])
65
+ assert path
66
+ puts "make Path : #{path}"
67
+ end
68
+
69
+ # NOTE We had to add the priority because Ruleby's conflict resolution strategy
70
+ # is not robust enough. If it worked like CLIPS, the priority would not
71
+ # be nessecary because the 'make path' activations would have more
72
+ # recent facts supporting it. This is really an error in the Miss Manners
73
+ # benchmark, so it is not considered cheating.
74
+ rule :pathDone, {:priority => -5},
75
+ [Context,:context, m.state == Context::MAKE_PATH],
76
+ [Seating,:seating, m.path == false] do |vars|
77
+ vars[:seating].path = true
78
+ modify vars[:seating]
79
+ vars[:context].state = Context::CHECK_DONE
80
+ modify vars[:context]
81
+ puts "path Done : #{vars[:seating]}"
82
+ end
83
+
84
+ rule :areWeDone,
85
+ [Context,:context, m.state == Context::CHECK_DONE],
86
+ [LastSeat,:ls, {m.seat => :lastSeat}],
87
+ [Seating,:seating, m.rightSeat == b(:lastSeat)] do |vars|
88
+ vars[:context].state = Context::PRINT_RESULTS
89
+ modify vars[:context]
90
+ end
91
+
92
+ rule :continue, {:priority => -5},
93
+ [Context,:context,m.state == Context::CHECK_DONE] do |vars|
94
+ vars[:context].state = Context::ASSIGN_SEATS
95
+ modify vars[:context]
96
+ end
97
+
98
+ rule :allDone,
99
+ [Context,:context,m.state == Context::PRINT_RESULTS] do |vars|
100
+ puts 'All done'
101
+ end
102
+ end
103
+ end
104
+
105
+ end