phenomenal 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/phenomenal.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'singleton'
1
2
  # Load the gem files in the system
2
3
  module Phenomenal
3
4
  module Viewer end
@@ -7,7 +7,7 @@ class Phenomenal::Context
7
7
 
8
8
  attr_accessor :activation_age, :activation_frequency, :adaptations,
9
9
  :activation_count, :parent, :forgotten
10
- attr_reader :manager,:name
10
+ attr_reader :manager,:name, :priority
11
11
  # Instance methods
12
12
  def initialize(name=nil, manager=nil)
13
13
  @manager = manager || Phenomenal::Manager.instance
@@ -18,6 +18,7 @@ class Phenomenal::Context
18
18
  @manager.register_context(self)
19
19
  @parent=nil
20
20
  @forgotten=false
21
+ @priority=nil
21
22
  end
22
23
 
23
24
  # Unregister the context from the context manager,
@@ -200,6 +201,13 @@ class Phenomenal::Context
200
201
  end
201
202
  end
202
203
 
204
+ def priority=(priority)
205
+ @priority=priority
206
+ return unless manager.shared_contexts[self]
207
+ manager.shared_contexts[self].each do |shared_context|
208
+ shared_context.priority=[priority,shared_context.priority].compact.min
209
+ end
210
+ end
203
211
  private
204
212
  def check_validity
205
213
  if forgotten
@@ -58,6 +58,9 @@ module Phenomenal::ContextCreation
58
58
  else
59
59
  c = self.new(c)
60
60
  end
61
+ # Inherit from parent priority
62
+ context.priority=[c.priority,context.priority].compact.min
63
+
61
64
  instances.push(c)
62
65
  manager.shared_contexts[c]= Array.new if !manager.shared_contexts[c]
63
66
  manager.shared_contexts[c].push(context)
@@ -19,6 +19,19 @@ module Phenomenal::ConflictPolicies
19
19
  context1.age <=> context2.age
20
20
  end
21
21
 
22
+ # Priority based conflict resolution
23
+ def priority_conflict_policy(context1, context2)
24
+ if context1.priority && !context2.priority
25
+ -1
26
+ elsif context2.priority && !context1.priority
27
+ 1
28
+ elsif context1.priority!=context2.priority
29
+ context1.priority <=> context2.priority
30
+ else
31
+ context1.age <=> context2.age
32
+ end
33
+ end
34
+
22
35
  # Resolution policy
23
36
  def conflict_policy(context1, context2)
24
37
  age_conflict_policy(context1, context2)
@@ -1,4 +1,3 @@
1
- require 'singleton'
2
1
  # This class manage the different contexts in the system and their interactions
3
2
  class Phenomenal::Manager
4
3
  include Singleton
@@ -1,3 +1,3 @@
1
1
  module Phenomenal
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
@@ -50,6 +50,7 @@ class Phenomenal::Viewer::Graphical
50
50
  self.main_graph = GraphViz::new("")
51
51
  # Default options
52
52
  self.main_graph[:compound] = "true"
53
+ self.main_graph[:rankdir]="LR"
53
54
  self.main_graph.edge[:lhead] = ""
54
55
  self.main_graph.edge[:ltail] = ""
55
56
  self.main_graph.edge[:fontsize] = 10.0
@@ -16,7 +16,7 @@ describe "Conflict policies" do
16
16
  adapt :advertise do |a_call|
17
17
  "vibrator"
18
18
  end
19
- end
19
+ end
20
20
  end
21
21
 
22
22
  after :each do
@@ -25,119 +25,266 @@ describe "Conflict policies" do
25
25
  phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
26
26
  end
27
27
 
28
- it "should not allow two contexts with an adaptation for the same method to be active at the same time" do
28
+ describe "No resolution conflict policy" do
29
+ it "should not allow two contexts with an adaptation for the same method to be active at the same time" do
29
30
 
30
- expect{activate_context(:screening)}.to_not raise_error
31
- expect{activate_context(:quiet)}.to raise_error Phenomenal::Error
31
+ expect{activate_context(:screening)}.to_not raise_error
32
+ expect{activate_context(:quiet)}.to raise_error Phenomenal::Error
33
+ end
32
34
  end
33
35
 
34
- it "should set the age of the context such that the most recent one has the smaller age" do
35
- phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
36
+ describe "Age resolution conflict policy" do
37
+ it "should set the age of the context such that the most recent one has the smaller age" do
38
+ phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
36
39
 
37
- phen_context_active?(phen_default_feature).should be_true
38
- phen_context_active?(:screening).should be_false
39
- phen_context_active?(:quiet).should be_false
40
+ phen_context_active?(phen_default_feature).should be_true
41
+ phen_context_active?(:screening).should be_false
42
+ phen_context_active?(:quiet).should be_false
40
43
 
41
- phen_activate_context(:screening)
44
+ phen_activate_context(:screening)
42
45
 
43
- (phen_context_information(:screening)[:age] <
44
- phen_context_information(phen_default_feature)[:age]).should be_true,
45
- "screening context has been activated more recently than default"
46
-
47
- phen_activate_context(:quiet)
48
- (phen_context_information(:quiet)[:age] <
49
- phen_context_information(:screening)[:age]).should be_true
50
- "quiet context has been activated more recently than screening"
51
- (phen_context_information(:screening)[:age] <
52
- phen_context_information(phen_default_feature)[:age]).should be_true,
53
- "quiet context has still been activated more recently than default"
54
- phen_deactivate_context(:quiet)
55
- phen_deactivate_context(:screening)
56
- phen_activate_context(:screening)
57
- (phen_context_information(:screening)[:age] <
58
- phen_context_information(:quiet)[:age]).should be_true,
59
- "screening context has now been activated more recently than quiet"
60
- end
46
+ (phen_context_information(:screening)[:age] <
47
+ phen_context_information(phen_default_feature)[:age]).should be_true,
48
+ "screening context has been activated more recently than default"
49
+
50
+ phen_activate_context(:quiet)
51
+ (phen_context_information(:quiet)[:age] <
52
+ phen_context_information(:screening)[:age]).should be_true
53
+ "quiet context has been activated more recently than screening"
54
+ (phen_context_information(:screening)[:age] <
55
+ phen_context_information(phen_default_feature)[:age]).should be_true,
56
+ "quiet context has still been activated more recently than default"
57
+ phen_deactivate_context(:quiet)
58
+ phen_deactivate_context(:screening)
59
+ phen_activate_context(:screening)
60
+ (phen_context_information(:screening)[:age] <
61
+ phen_context_information(:quiet)[:age]).should be_true,
62
+ "screening context has now been activated more recently than quiet"
63
+ end
61
64
 
62
- it "should choose the context the most recently activated" do
63
- phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
64
- expect{activate_context(:screening)}.to_not raise_error
65
- expect{activate_context(:quiet)}.to_not raise_error
66
- end
65
+ it "should choose the context the most recently activated" do
66
+ phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
67
+ expect{activate_context(:screening)}.to_not raise_error
68
+ expect{activate_context(:quiet)}.to_not raise_error
69
+ end
67
70
 
68
- it "should work with interleaved activation of contexts" do
69
- phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
70
- phone = Phone.new
71
- call = Call.new("Alice")
72
- phone.receive(call)
71
+ it "should work with interleaved activation of contexts" do
72
+ phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
73
+ phone = Phone.new
74
+ call = Call.new("Alice")
75
+ phone.receive(call)
73
76
 
74
- phone.advertise(call).should=="ringtone"
77
+ phone.advertise(call).should=="ringtone"
75
78
 
76
- activate_context(:quiet)
77
- phone.advertise(call).should=="vibrator"
79
+ activate_context(:quiet)
80
+ phone.advertise(call).should=="vibrator"
78
81
 
79
- activate_context(:screening)
80
- phone.advertise(call).should=="vibrator with screening"
82
+ activate_context(:screening)
83
+ phone.advertise(call).should=="vibrator with screening"
81
84
 
82
- deactivate_context(:quiet)
83
- phone.advertise(call).should=="ringtone with screening"
85
+ deactivate_context(:quiet)
86
+ phone.advertise(call).should=="ringtone with screening"
84
87
 
85
- deactivate_context(:screening)
86
- phone.advertise(call).should=="ringtone"
87
- end
88
+ deactivate_context(:screening)
89
+ phone.advertise(call).should=="ringtone"
90
+ end
88
91
 
89
- it "should nest calls with the age policy" do
90
- phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
91
- phone = Phone.new
92
- call = Call.new("Alice")
93
- phone.receive(call)
92
+ it "should nest calls with the age policy" do
93
+ phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
94
+ phone = Phone.new
95
+ call = Call.new("Alice")
96
+ phone.receive(call)
94
97
 
95
- phone.advertise(call).should=="ringtone"
98
+ phone.advertise(call).should=="ringtone"
96
99
 
97
- activate_context(:quiet)
98
- phone.advertise(call).should=="vibrator"
100
+ activate_context(:quiet)
101
+ phone.advertise(call).should=="vibrator"
99
102
 
100
- activate_context(:screening)
101
- phone.advertise(call).should=="vibrator with screening"
103
+ activate_context(:screening)
104
+ phone.advertise(call).should=="vibrator with screening"
102
105
 
103
- deactivate_context(:screening)
104
- phone.advertise(call).should=="vibrator"
106
+ deactivate_context(:screening)
107
+ phone.advertise(call).should=="vibrator"
105
108
 
106
- deactivate_context(:quiet)
107
- phone.advertise(call).should=="ringtone"
109
+ deactivate_context(:quiet)
110
+ phone.advertise(call).should=="ringtone"
111
+ end
112
+
113
+ it "should proceed adaptations in the rigth order" do
114
+ phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
115
+ context(:level1)
116
+ phen_add_adaptation(:level1,TestClass,:print) do |arg|
117
+ phen_proceed(arg) + " 1 -> ARG1: #{arg.to_s}"
118
+ end
119
+
120
+ context(:level2)
121
+ phen_add_adaptation(:level2,TestClass,:print) do |arg|
122
+ phen_proceed(arg) + " 2 -> ARG2: #{arg.to_s}"
123
+ end
124
+
125
+ context(:level3)
126
+ phen_add_adaptation(:level3,TestClass,:print) do |arg|
127
+ phen_proceed(arg) + " 3 -> ARG3: #{arg.to_s}"
128
+ end
129
+
130
+ context(:level4)
131
+ phen_add_adaptation(:level4,TestClass,:print) do |arg|
132
+ phen_proceed(arg) + " 4 -> ARG4: #{arg.to_s}"
133
+ end
134
+ t = TestClass.new("Foo")
135
+ t.print("bar").should=="0 -> ARG: bar"
136
+ activate_context(:level1)
137
+ activate_context(:level2)
138
+ activate_context(:level3)
139
+ activate_context(:level4)
140
+ t.print("bar").should=="0 -> ARG: bar 1 -> ARG1: bar 2 -> ARG2: bar 3 -> ARG3: bar 4 -> ARG4: bar"
141
+ force_forget_context(:level1)
142
+ force_forget_context(:level2)
143
+ force_forget_context(:level3)
144
+ force_forget_context(:level4)
145
+ end
108
146
  end
109
147
 
110
- it "should proceed adaptations in the rigth order" do
111
- phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
112
- context(:level1)
113
- phen_add_adaptation(:level1,TestClass,:print) do |arg|
114
- phen_proceed(arg) + " 1 -> ARG1: #{arg.to_s}"
148
+ describe "Priority conflict resolution policy" do
149
+ it "should behave like age when no priorities defined" do
150
+ phen_change_conflict_policy { |a,b| priority_conflict_policy(a,b) }
151
+ phone = Phone.new
152
+ call = Call.new("Alice")
153
+ phone.receive(call)
154
+
155
+ phone.advertise(call).should=="ringtone"
156
+
157
+ activate_context(:quiet)
158
+ phone.advertise(call).should=="vibrator"
159
+
160
+ activate_context(:screening)
161
+ phone.advertise(call).should=="vibrator with screening"
162
+
163
+ deactivate_context(:quiet)
164
+ phone.advertise(call).should=="ringtone with screening"
165
+
166
+ deactivate_context(:screening)
167
+ phone.advertise(call).should=="ringtone"
115
168
  end
169
+
170
+ it "should use priorities when defined" do
171
+ phen_change_conflict_policy { |a,b| priority_conflict_policy(a,b) }
172
+ phone = Phone.new
173
+ call = Call.new("Alice")
174
+ context(:quiet).priority=1
175
+ context(:screening).priority=2
176
+
177
+ phone.receive(call)
178
+
179
+ phone.advertise(call).should=="ringtone"
116
180
 
117
- context(:level2)
118
- phen_add_adaptation(:level2,TestClass,:print) do |arg|
119
- phen_proceed(arg) + " 2 -> ARG2: #{arg.to_s}"
181
+ activate_context(:quiet)
182
+ phone.advertise(call).should=="vibrator"
183
+
184
+ activate_context(:screening)
185
+ phone.advertise(call).should=="vibrator"
186
+
187
+ deactivate_context(:quiet)
188
+ phone.advertise(call).should=="ringtone with screening"
189
+
190
+ deactivate_context(:screening)
191
+ phone.advertise(call).should=="ringtone"
120
192
  end
193
+ it "should behave like age when priorities are equal" do
194
+ phen_change_conflict_policy { |a,b| priority_conflict_policy(a,b) }
195
+ phone = Phone.new
196
+ call = Call.new("Alice")
197
+ context(:quiet).priority=2
198
+ context(:screening).priority=2
199
+ phone.receive(call)
200
+
201
+ phone.advertise(call).should=="ringtone"
202
+
203
+ activate_context(:quiet)
204
+ phone.advertise(call).should=="vibrator"
205
+
206
+ activate_context(:screening)
207
+ phone.advertise(call).should=="vibrator with screening"
208
+
209
+ deactivate_context(:quiet)
210
+ phone.advertise(call).should=="ringtone with screening"
211
+
212
+ deactivate_context(:screening)
213
+ phone.advertise(call).should=="ringtone"
214
+ end
215
+
216
+ it "should prefer priority over age" do
217
+ phen_change_conflict_policy { |a,b| priority_conflict_policy(a,b) }
218
+ phone = Phone.new
219
+ call = Call.new("Alice")
220
+ context(:quiet).priority=1
221
+
222
+ phone.receive(call)
121
223
 
122
- context(:level3)
123
- phen_add_adaptation(:level3,TestClass,:print) do |arg|
124
- phen_proceed(arg) + " 3 -> ARG3: #{arg.to_s}"
224
+ phone.advertise(call).should=="ringtone"
225
+
226
+ activate_context(:quiet)
227
+ phone.advertise(call).should=="vibrator"
228
+
229
+ activate_context(:screening)
230
+ phone.advertise(call).should=="vibrator"
231
+
232
+ deactivate_context(:quiet)
233
+ phone.advertise(call).should=="ringtone with screening"
234
+
235
+ deactivate_context(:screening)
236
+ phone.advertise(call).should=="ringtone"
125
237
  end
238
+
239
+ it "should prefer combined context" do
240
+ phen_change_conflict_policy { |a,b| priority_conflict_policy(a,b) }
241
+ phone = Phone.new
242
+ call = Call.new("Alice")
243
+ combined_context=context :screening, :quiet do
244
+ adaptations_for Phone
245
+ adapt :advertise do |a_call|
246
+ "combined"
247
+ end
248
+ end
249
+ context(:quiet).priority=1
250
+ context(:screening).priority=2
251
+
252
+
253
+ phone.receive(call)
254
+
255
+ phone.advertise(call).should=="ringtone"
256
+
257
+ activate_context(:quiet)
258
+ phone.advertise(call).should=="vibrator"
259
+
260
+ activate_context(:screening)
261
+ phone.advertise(call).should=="combined"
262
+
263
+ deactivate_context(:quiet)
264
+ phone.advertise(call).should=="ringtone with screening"
265
+
266
+ deactivate_context(:screening)
267
+ phone.advertise(call).should=="ringtone"
268
+
269
+ # Invert priority
270
+ context(:quiet).priority=2
271
+ context(:screening).priority=1
272
+
273
+ phone.advertise(call).should=="ringtone"
274
+
275
+ activate_context(:quiet)
276
+ phone.advertise(call).should=="vibrator"
277
+
278
+ activate_context(:screening)
279
+ phone.advertise(call).should=="combined"
280
+
281
+ deactivate_context(:quiet)
282
+ phone.advertise(call).should=="ringtone with screening"
126
283
 
127
- context(:level4)
128
- phen_add_adaptation(:level4,TestClass,:print) do |arg|
129
- phen_proceed(arg) + " 4 -> ARG4: #{arg.to_s}"
284
+ deactivate_context(:screening)
285
+ phone.advertise(call).should=="ringtone"
286
+
287
+ combined_context.forget
130
288
  end
131
- t = TestClass.new("Foo")
132
- t.print("bar").should=="0 -> ARG: bar"
133
- activate_context(:level1)
134
- activate_context(:level2)
135
- activate_context(:level3)
136
- activate_context(:level4)
137
- t.print("bar").should=="0 -> ARG: bar 1 -> ARG1: bar 2 -> ARG2: bar 3 -> ARG3: bar 4 -> ARG4: bar"
138
- force_forget_context(:level1)
139
- force_forget_context(:level2)
140
- force_forget_context(:level3)
141
- force_forget_context(:level4)
142
289
  end
143
290
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phenomenal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-01 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec