yasm 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +64 -4
- data/VERSION +1 -1
- data/lib/yasm.rb +2 -0
- data/lib/yasm/context.rb +2 -5
- data/lib/yasm/context/state_container.rb +2 -0
- data/lib/yasm/exceptions.rb +3 -0
- data/lib/yasm/exceptions/final_state_exception.rb +3 -0
- data/lib/yasm/exceptions/invalid_action_exception.rb +3 -0
- data/lib/yasm/exceptions/time_limit_not_yet_reached.rb +4 -0
- data/lib/yasm/manager.rb +11 -3
- data/lib/yasm/state.rb +39 -0
- data/spec/yasm/manager_spec.rb +79 -46
- data/spec/yasm/state_container_spec.rb +37 -0
- data/spec/yasm/state_spec.rb +77 -0
- data/yasm.gemspec +6 -2
- metadata +8 -4
data/README.markdown
CHANGED
@@ -93,7 +93,7 @@ invalid actions to the context, `Yasm` will raise an exception.
|
|
93
93
|
#==> Waiting
|
94
94
|
|
95
95
|
vending_machine.do! RetrieveSelection
|
96
|
-
#==>
|
96
|
+
#==> InvalidActionException: We're sorry, but the action `RetrieveSelection`
|
97
97
|
is not possible given the current state `Waiting`.
|
98
98
|
|
99
99
|
vending_machine.do! InputMoney
|
@@ -101,7 +101,8 @@ invalid actions to the context, `Yasm` will raise an exception.
|
|
101
101
|
vending_machine.state.value
|
102
102
|
#==> Waiting
|
103
103
|
|
104
|
-
|
104
|
+
|
105
|
+
### Side Effects
|
105
106
|
|
106
107
|
How can we take our simulation farther? A real vending machine would verify that when you make a selection,
|
107
108
|
you actually have input enough money to pay for that selection. How can we model this?
|
@@ -197,7 +198,7 @@ pay for our selection).
|
|
197
198
|
#==> Waiting
|
198
199
|
|
199
200
|
|
200
|
-
|
201
|
+
### End states
|
201
202
|
|
202
203
|
Sometimes, a state is final. Like, what if, out of frustration, you threw the vending machine off the top of a 10 story building? It's probably not going
|
203
204
|
to work again after that. You can use the `final!` macro on a state to denote that this is the end.
|
@@ -219,8 +220,67 @@ to work again after that. You can use the `final!` macro on a state to denote th
|
|
219
220
|
vending_machine.do! TossOffBuilding
|
220
221
|
|
221
222
|
vending_machine.do! MakeSelection.new(SnickersBar)
|
222
|
-
#==>
|
223
|
+
#==> Yasm::FinalStateException: We're sorry, but the current state `Obliterated` is final. It does not accept any actions.
|
224
|
+
|
225
|
+
|
226
|
+
### State Timers
|
227
|
+
|
228
|
+
When a vending machine vends an item, it takes about 10 seconds for the item to work it's way off the rack and fall to the bottom. We can simulate this
|
229
|
+
by placing a `minimum` constraint on the `Vending` state.
|
230
|
+
|
231
|
+
class Vending
|
232
|
+
include Yasm::State
|
233
|
+
|
234
|
+
minimum 10.seconds
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
Now, when we go into the vending state, we won't be able to retrieve our selection until 10 seconds have passed.
|
239
|
+
|
240
|
+
vending_machine.do! MakeSelection.new(SnickersBar)
|
241
|
+
|
242
|
+
vending_machine.state.value
|
243
|
+
#==> Vending
|
244
|
+
|
245
|
+
vending_machine.do! RetrieveSelection
|
246
|
+
#==> Yasm::TimeLimitNotYetReached: We're sorry, but the time limit on the state `Vending` has not yet been reached.
|
247
|
+
|
248
|
+
sleep 10
|
249
|
+
|
250
|
+
vending_machine.do! RetrieveSelection
|
251
|
+
|
252
|
+
vending_machine.state.value
|
253
|
+
#==> Waiting
|
254
|
+
|
255
|
+
You can also create maximum time limits. For example, suppose we want our vending machine to self destruct, out of frustration, if it goes
|
256
|
+
an entire minute without any action.
|
257
|
+
|
258
|
+
class Waiting
|
259
|
+
include Yasm::State
|
260
|
+
|
261
|
+
maximum 1.minute, :action => :self_destruct
|
262
|
+
end
|
263
|
+
|
264
|
+
class SelfDestruct
|
265
|
+
include Yasm::Action
|
266
|
+
|
267
|
+
triggers :obliterated
|
223
268
|
|
269
|
+
def execute
|
270
|
+
puts "KABOOM!"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
Now, if we create a vending machine, then wait at least a minute, next time we try to do something to it, it will execute the `SelfDestruct` action.
|
275
|
+
|
276
|
+
|
277
|
+
v = VendingMachine.new
|
278
|
+
|
279
|
+
sleep 60
|
280
|
+
|
281
|
+
v.do! InputMoney.new(10)
|
282
|
+
#==> "KABOOM!"
|
283
|
+
#==> Yasm::FinalStateException: We're sorry, but the current state `Obliterated` is final. It does not accept any actions.
|
224
284
|
|
225
285
|
|
226
286
|
## PUBLIC DOMAIN
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/yasm.rb
CHANGED
data/lib/yasm/context.rb
CHANGED
@@ -45,11 +45,8 @@ module Yasm
|
|
45
45
|
|
46
46
|
def state_container(id)
|
47
47
|
unless state_containers[id]
|
48
|
-
state_containers[id] =
|
49
|
-
|
50
|
-
:context => self,
|
51
|
-
:state => self.class.state_configurations[id].start_state.to_class.new
|
52
|
-
)
|
48
|
+
state_containers[id] = StateContainer.new :context => self
|
49
|
+
Yasm::Manager.change_state :to => self.class.state_configurations[id].start_state, :on => state_containers[id]
|
53
50
|
end
|
54
51
|
|
55
52
|
state_containers[id]
|
data/lib/yasm/manager.rb
CHANGED
@@ -5,9 +5,17 @@ module Yasm
|
|
5
5
|
def change_state(options)
|
6
6
|
new_state = options[:to]
|
7
7
|
state_container = options[:on]
|
8
|
+
|
9
|
+
raise(
|
10
|
+
Yasm::TimeLimitNotYetReached,
|
11
|
+
"We're sorry, but the time limit on the state `#{state_container.state}` has not yet been reached."
|
12
|
+
) if state_container.state and !state_container.state.reached_minimum_time_limit?
|
13
|
+
|
8
14
|
new_state = new_state.to_class if new_state.respond_to? :to_class
|
15
|
+
new_state = new_state.new
|
16
|
+
new_state.instantiated_at = Time.now
|
9
17
|
|
10
|
-
state_container.state = new_state
|
18
|
+
state_container.state = new_state
|
11
19
|
end
|
12
20
|
|
13
21
|
def execute(options)
|
@@ -23,9 +31,9 @@ module Yasm
|
|
23
31
|
|
24
32
|
# Verify that the action is possible given the current state
|
25
33
|
if state_container.state.class.final?
|
26
|
-
raise "We're sorry, but the current state `#{state_container.state}` is final. It does not accept any actions."
|
34
|
+
raise Yasm::FinalStateException, "We're sorry, but the current state `#{state_container.state}` is final. It does not accept any actions."
|
27
35
|
elsif !state_container.state.class.is_allowed?(action.class)
|
28
|
-
raise "We're sorry, but the action `#{action.class}` is not possible given the current state `#{state_container.state}`."
|
36
|
+
raise Yasm::InvalidActionException, "We're sorry, but the action `#{action.class}` is not possible given the current state `#{state_container.state}`."
|
29
37
|
end
|
30
38
|
|
31
39
|
change_state :to => action.triggers.to_class, :on => state_container if action.triggers
|
data/lib/yasm/state.rb
CHANGED
@@ -25,10 +25,49 @@ module Yasm
|
|
25
25
|
def final?
|
26
26
|
@allowed_actions == []
|
27
27
|
end
|
28
|
+
|
29
|
+
def minimum(time)
|
30
|
+
raise(
|
31
|
+
ArgumentError,
|
32
|
+
"You must provide a Fixnum to the ##minimum method (represents number of seconds). For example: 2.minutes"
|
33
|
+
) unless time.kind_of?(Fixnum)
|
34
|
+
|
35
|
+
@state_minimum_duration = time
|
36
|
+
end
|
37
|
+
|
38
|
+
def minimum_duration
|
39
|
+
@state_minimum_duration
|
40
|
+
end
|
41
|
+
|
42
|
+
def maximum(maximum_duration, action_hash)
|
43
|
+
@maximum_duration = maximum_duration
|
44
|
+
@maximum_duration_action = action_hash[:action]
|
45
|
+
end
|
46
|
+
|
47
|
+
def maximum_duration
|
48
|
+
@maximum_duration
|
49
|
+
end
|
50
|
+
|
51
|
+
def maximum_duration_action
|
52
|
+
return @maximum_duration_action.call if @maximum_duration_action.respond_to? :call
|
53
|
+
@maximum_duration_action.to_class
|
54
|
+
end
|
28
55
|
end
|
56
|
+
|
57
|
+
attr_accessor :instantiated_at
|
29
58
|
|
30
59
|
def to_s
|
31
60
|
self.class.to_s
|
32
61
|
end
|
62
|
+
|
63
|
+
def reached_minimum_time_limit?
|
64
|
+
return true unless self.class.minimum_duration
|
65
|
+
(Time.now - instantiated_at) >= self.class.minimum_duration
|
66
|
+
end
|
67
|
+
|
68
|
+
def passed_maximum_time_limit?
|
69
|
+
return false unless self.class.maximum_duration
|
70
|
+
(Time.now - instantiated_at) >= self.class.maximum_duration
|
71
|
+
end
|
33
72
|
end
|
34
73
|
end
|
data/spec/yasm/manager_spec.rb
CHANGED
@@ -1,53 +1,82 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Yasm::Manager do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
4
|
+
before do
|
5
|
+
class VendingMachine
|
6
|
+
include Yasm::Context
|
7
|
+
|
8
|
+
start :on
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
class Unplug
|
12
|
+
include Yasm::Action
|
13
|
+
|
14
|
+
triggers :off
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
class PlugIn
|
18
|
+
include Yasm::Action
|
19
|
+
|
20
|
+
triggers :on
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
class Destroy
|
24
|
+
include Yasm::Action
|
26
25
|
|
27
|
-
|
28
|
-
|
26
|
+
triggers :destroyed
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
class On
|
30
|
+
include Yasm::State
|
31
|
+
|
32
|
+
actions :unplug, :destroy
|
33
|
+
end
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
class Off
|
36
|
+
include Yasm::State
|
37
|
+
|
38
|
+
actions :plug_in, :destroy
|
39
|
+
end
|
40
|
+
|
41
|
+
class Destroyed
|
42
|
+
include Yasm::State
|
43
|
+
|
44
|
+
final!
|
45
|
+
end
|
46
|
+
|
47
|
+
@vending_machine = VendingMachine.new
|
48
|
+
end
|
49
|
+
|
41
50
|
|
42
|
-
|
51
|
+
|
52
|
+
describe "##change_state" do
|
53
|
+
it "should convert the state to a class if we pass an object that respond to :to_class" do
|
54
|
+
Destroyed.should_receive(:to_class).and_return Destroyed
|
55
|
+
Yasm::Manager.change_state :to => Destroyed, :on => @vending_machine.state
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should set the instantiated_at property on the state to the current time" do
|
59
|
+
seconds_since_the_epoch = Time.now
|
60
|
+
Time.should_receive(:now).twice.and_return seconds_since_the_epoch
|
61
|
+
Yasm::Manager.change_state :to => On, :on => @vending_machine.state
|
62
|
+
@vending_machine.state.value.instantiated_at.should == seconds_since_the_epoch
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should raise an exception if the current state has not yet reached it's time limit" do
|
66
|
+
class TenSeconds
|
43
67
|
include Yasm::State
|
44
68
|
|
45
|
-
|
69
|
+
minimum 10.seconds
|
46
70
|
end
|
47
|
-
|
48
|
-
|
71
|
+
|
72
|
+
proc {
|
73
|
+
Yasm::Manager.change_state :to => TenSeconds, :on => @vending_machine.state
|
74
|
+
Yasm::Manager.change_state :to => On, :on => @vending_machine.state
|
75
|
+
}.should raise_exception(Yasm::TimeLimitNotYetReached, "We're sorry, but the time limit on the state `TenSeconds` has not yet been reached.")
|
49
76
|
end
|
50
|
-
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "##execute" do
|
51
80
|
it "should apply each action, sequentially, to the appropriate state_container within the context" do
|
52
81
|
@vending_machine.state.value.class.should == On
|
53
82
|
|
@@ -58,7 +87,7 @@ describe Yasm::Manager do
|
|
58
87
|
@vending_machine.state.value.class.should == On
|
59
88
|
end
|
60
89
|
|
61
|
-
it "should
|
90
|
+
it "should raise an exception if you attempt to execute an action that isn't allowed by a state" do
|
62
91
|
@vending_machine.state.value.class.should == On
|
63
92
|
|
64
93
|
proc {
|
@@ -67,8 +96,20 @@ describe Yasm::Manager do
|
|
67
96
|
:state_container => @vending_machine.state,
|
68
97
|
:actions => [PlugIn]
|
69
98
|
)
|
70
|
-
}.should raise_exception("We're sorry, but the action `PlugIn` is not possible given the current state `On`.")
|
99
|
+
}.should raise_exception(Yasm::InvalidActionException, "We're sorry, but the action `PlugIn` is not possible given the current state `On`.")
|
100
|
+
end
|
71
101
|
|
102
|
+
it "should raise an exception if you attempt to execute an action on a final state." do
|
103
|
+
proc {
|
104
|
+
Yasm::Manager.execute(
|
105
|
+
:context => @vending_machine,
|
106
|
+
:state_container => @vending_machine.state,
|
107
|
+
:actions => [Destroy, PlugIn]
|
108
|
+
)
|
109
|
+
}.should raise_exception(Yasm::FinalStateException, "We're sorry, but the current state `Destroyed` is final. It does not accept any actions.")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should not raise an exception if the action is allowed by the state" do
|
72
113
|
proc {
|
73
114
|
Yasm::Manager.execute(
|
74
115
|
:context => @vending_machine,
|
@@ -76,14 +117,6 @@ describe Yasm::Manager do
|
|
76
117
|
:actions => [Unplug]
|
77
118
|
)
|
78
119
|
}.should_not raise_exception
|
79
|
-
|
80
|
-
proc {
|
81
|
-
Yasm::Manager.execute(
|
82
|
-
:context => @vending_machine,
|
83
|
-
:state_container => @vending_machine.state,
|
84
|
-
:actions => [Destroy, PlugIn]
|
85
|
-
)
|
86
|
-
}.should raise_exception("We're sorry, but the current state `Destroyed` is final. It does not accept any actions.")
|
87
120
|
end
|
88
121
|
end
|
89
122
|
end
|
@@ -4,11 +4,39 @@ describe Yasm::Context::StateContainer do
|
|
4
4
|
before do
|
5
5
|
class VendingMachine
|
6
6
|
include Yasm::Context
|
7
|
+
|
8
|
+
start :waiting
|
7
9
|
end
|
8
10
|
|
9
11
|
class Waiting
|
10
12
|
include Yasm::State
|
11
13
|
end
|
14
|
+
|
15
|
+
class Hit
|
16
|
+
include Yasm::Action
|
17
|
+
|
18
|
+
triggers :jammed
|
19
|
+
end
|
20
|
+
|
21
|
+
class Jammed
|
22
|
+
include Yasm::State
|
23
|
+
|
24
|
+
maximum 10.seconds, :action => :explode
|
25
|
+
end
|
26
|
+
|
27
|
+
class Exploded
|
28
|
+
include Yasm::State
|
29
|
+
|
30
|
+
actions :clean_up
|
31
|
+
end
|
32
|
+
|
33
|
+
class CleanUp
|
34
|
+
include Yasm::Action
|
35
|
+
end
|
36
|
+
|
37
|
+
class Explode
|
38
|
+
include Yasm::Action
|
39
|
+
end
|
12
40
|
|
13
41
|
class InputMoney
|
14
42
|
include Yasm::Action
|
@@ -21,5 +49,14 @@ describe Yasm::Context::StateContainer do
|
|
21
49
|
Yasm::Manager.should_receive(:execute).with(:context => v, :state_container => v.state, :actions => [InputMoney, InputMoney])
|
22
50
|
v.state.do! InputMoney, InputMoney
|
23
51
|
end
|
52
|
+
|
53
|
+
it "should add the maximum action to the front of the action list if the maximum time limit has been reached" do
|
54
|
+
v = VendingMachine.new
|
55
|
+
v.do! Hit
|
56
|
+
Yasm::Manager.should_receive(:execute).with(:context => v, :state_container => v.state, :actions => [Explode, CleanUp])
|
57
|
+
time = 10.seconds.from_now
|
58
|
+
Time.stub!(:now).and_return time
|
59
|
+
v.do! CleanUp
|
60
|
+
end
|
24
61
|
end
|
25
62
|
end
|
data/spec/yasm/state_spec.rb
CHANGED
@@ -30,4 +30,81 @@ describe Yasm::State do
|
|
30
30
|
TestState.final?.should be_true
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
describe "##minimum" do
|
35
|
+
it "should require an integer" do
|
36
|
+
proc { TestState.minimum "10 minutes" }.should raise_exception("You must provide a Fixnum to the ##minimum method (represents number of seconds). For example: 2.minutes")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should set the @state_minimum_duration to the number input" do
|
40
|
+
TestState.minimum 1.minute
|
41
|
+
TestState.minimum_duration.should == 60
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#reached_minimum_time_limit?" do
|
46
|
+
before do
|
47
|
+
class MinState
|
48
|
+
include Yasm::State
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return true if there is no minimum time limit for the state" do
|
53
|
+
MinState.new.reached_minimum_time_limit?.should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return false if there is a time limit that hasn't been reached yet" do
|
57
|
+
MinState.minimum 10.seconds
|
58
|
+
state = MinState.new
|
59
|
+
state.instantiated_at = Time.now
|
60
|
+
state.reached_minimum_time_limit?.should be_false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return true if the state has reached it's time limit" do
|
64
|
+
MinState.minimum 10.seconds
|
65
|
+
state = MinState.new
|
66
|
+
state.instantiated_at = Time.now
|
67
|
+
ten_seconds_from_now = 10.seconds.from_now
|
68
|
+
Time.should_receive(:now).and_return ten_seconds_from_now
|
69
|
+
state.reached_minimum_time_limit?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "##maximum" do
|
74
|
+
it "should require both a time limit and an action" do
|
75
|
+
proc { TestState.maximum }.should raise_exception(ArgumentError)
|
76
|
+
proc { TestState.maximum 10.seconds }.should raise_exception(ArgumentError)
|
77
|
+
proc { TestState.maximum 10.seconds, :action => :action1 }.should_not raise_exception
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should store the time limit and action" do
|
81
|
+
TestState.maximum 20.seconds, :action => :action2
|
82
|
+
TestState.maximum_duration.should == 20.seconds
|
83
|
+
TestState.maximum_duration_action.should == Action2
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "##passed_maximum_time_limit?" do
|
88
|
+
it "should return false if no time limit has been set" do
|
89
|
+
class UnlimitedState
|
90
|
+
include Yasm::State
|
91
|
+
end
|
92
|
+
|
93
|
+
UnlimitedState.new.passed_maximum_time_limit?.should be_false
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return true if a time limit was set, and that limit has been passed" do
|
97
|
+
class LimitedState
|
98
|
+
include Yasm::State
|
99
|
+
|
100
|
+
maximum 10.seconds, :action => :action2
|
101
|
+
end
|
102
|
+
|
103
|
+
s = LimitedState.new
|
104
|
+
s.instantiated_at = Time.now
|
105
|
+
ten_seconds_from_now = 10.seconds.from_now
|
106
|
+
Time.stub!(:now).and_return ten_seconds_from_now
|
107
|
+
s.passed_maximum_time_limit?.should be_true
|
108
|
+
end
|
109
|
+
end
|
33
110
|
end
|
data/yasm.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{yasm}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matt Parker"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-13}
|
13
13
|
s.description = %q{Breaks up states, actions, and contexts into seperate classes.moonmaster9000@gmail.com}
|
14
14
|
s.email = %q{moonmaster9000@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,6 +26,10 @@ Gem::Specification.new do |s|
|
|
26
26
|
"lib/yasm/conversions.rb",
|
27
27
|
"lib/yasm/conversions/class.rb",
|
28
28
|
"lib/yasm/conversions/symbol.rb",
|
29
|
+
"lib/yasm/exceptions.rb",
|
30
|
+
"lib/yasm/exceptions/final_state_exception.rb",
|
31
|
+
"lib/yasm/exceptions/invalid_action_exception.rb",
|
32
|
+
"lib/yasm/exceptions/time_limit_not_yet_reached.rb",
|
29
33
|
"lib/yasm/manager.rb",
|
30
34
|
"lib/yasm/state.rb",
|
31
35
|
"lib/yasm/version.rb",
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yasm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Parker
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-13 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -68,6 +68,10 @@ files:
|
|
68
68
|
- lib/yasm/conversions.rb
|
69
69
|
- lib/yasm/conversions/class.rb
|
70
70
|
- lib/yasm/conversions/symbol.rb
|
71
|
+
- lib/yasm/exceptions.rb
|
72
|
+
- lib/yasm/exceptions/final_state_exception.rb
|
73
|
+
- lib/yasm/exceptions/invalid_action_exception.rb
|
74
|
+
- lib/yasm/exceptions/time_limit_not_yet_reached.rb
|
71
75
|
- lib/yasm/manager.rb
|
72
76
|
- lib/yasm/state.rb
|
73
77
|
- lib/yasm/version.rb
|