phenomenal 1.2.2 → 1.2.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.
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