ruleby 0.9.b4 → 0.9.b7
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/.gitignore +5 -0
- data/GPL.txt +341 -0
- data/LICENSE.txt +52 -0
- data/README.markdown +22 -0
- data/benchmarks/basic_rules.rb +61 -0
- data/benchmarks/joined_rules.rb +66 -0
- data/benchmarks/miss_manners/data.rb +146 -0
- data/benchmarks/miss_manners/miss_manners.rb +33 -0
- data/benchmarks/miss_manners/model.rb +193 -0
- data/benchmarks/miss_manners/rules.rb +105 -0
- data/benchmarks/model.rb +36 -0
- data/examples/diagnosis.rb +129 -0
- data/examples/fibonacci_example1.rb +44 -0
- data/examples/fibonacci_example2.rb +40 -0
- data/examples/fibonacci_example3.rb +78 -0
- data/examples/fibonacci_rulebook.rb +84 -0
- data/examples/hello.rb +45 -0
- data/examples/ticket.rb +113 -0
- data/examples/wordgame.rb +107 -0
- data/lib/core/engine.rb +26 -24
- data/lib/core/nodes.rb +77 -35
- data/lib/ruleby.rb +0 -37
- data/ruleby.gemspec +17 -0
- data/spec/and_or_spec.rb +252 -0
- data/spec/coercion_spec.rb +5 -0
- data/spec/collect_spec.rb +1021 -0
- data/spec/errors_spec.rb +148 -0
- data/spec/ferrari_spec.rb +39 -0
- data/spec/function_spec.rb +199 -0
- data/spec/hello_spec.rb +34 -0
- data/spec/node_sharing_spec.rb +53 -0
- data/spec/property_spec.rb +69 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +9 -0
- data/tasks/documentation.rake +32 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/test.rake +9 -0
- data/tests/assert_facts.rb +130 -0
- data/tests/common.rb +29 -0
- data/tests/duck_type.rb +79 -0
- data/tests/gets.rb +48 -0
- data/tests/join_nodes.rb +63 -0
- data/tests/nil.rb +72 -0
- data/tests/not_patterns.rb +91 -0
- data/tests/or_patterns.rb +154 -0
- data/tests/regex.rb +47 -0
- data/tests/self_reference.rb +54 -0
- 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
|