pretty-fsm 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,10 @@
1
+ Manifest
2
+ README
3
+ Rakefile
4
+ examples/door.rb
5
+ examples/timed_door.rb
6
+ lib/pretty-fsm.rb
7
+ lib/pretty-fsm/fsm.rb
8
+ lib/pretty-fsm/timed_event.rb
9
+ nbproject/project.properties
10
+ nbproject/project.xml
data/README ADDED
@@ -0,0 +1,7 @@
1
+ = Usage and examples
2
+
3
+ Look under the +examples+ directory
4
+
5
+ = License
6
+
7
+ This ruby module is licensed under the GPLv2
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ # -*- ruby -*-
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'echoe'
5
+ #require 'yard'
6
+
7
+ Echoe.new('pretty-fsm') do |p|
8
+ p.author = 'v01d'
9
+ p.summary = "Finite State Machine class with intuitive integration"
10
+ p.url = "http://github.com/v01d/pretty-fsm"
11
+ p.version = "0.1"
12
+ # p.dependencies = ['yard']
13
+ # p.eval = proc { s.has_rdoc = 'yard' }
14
+ end
15
+
16
+ #Rake::TaskManager.class_eval do
17
+ # def remove_task(task)
18
+ # @tasks.delete(task.to_s)
19
+ # end
20
+ #end
21
+
22
+ #Rake.application.remove_task(:docs)
23
+ #YARD::Rake::YardocTask.new(:docs) {|t| t.options = ['--verbose','--no-private','--hide-void']}
24
+
data/examples/door.rb ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/ruby -w
2
+ require 'pretty-fsm'
3
+
4
+ class Door
5
+ include PrettyFSM::Abbreviate
6
+
7
+ attr_reader(:fsm)
8
+
9
+ def initialize
10
+ @fsm = PrettyFSM::FSM.new(self, :open) do
11
+ transition :from => :open, :to => :close, :if => :can_close?
12
+ transition :from => :close, :to => :open, :if => :can_open?
13
+ end
14
+ end
15
+
16
+ def run
17
+ loop do
18
+ @fsm.advance
19
+ sleep(0.25)
20
+ end
21
+ end
22
+
23
+ def start_open
24
+ puts "Openned door"
25
+ @counter = 10
26
+ end
27
+
28
+ def while_open
29
+ @counter -= 1
30
+ puts @counter.to_s
31
+ end
32
+
33
+ def can_close?
34
+ @counter == 0
35
+ end
36
+
37
+ def start_close
38
+ puts "Closed door"
39
+ end
40
+
41
+ def while_close
42
+ @counter += 1
43
+ puts @counter.to_s
44
+ end
45
+
46
+ def can_open?
47
+ @counter == 10
48
+ end
49
+ end
50
+
51
+ Door.new.run
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/ruby -w
2
+ require 'pretty-fsm'
3
+
4
+ class Door
5
+ include PrettyFSM::Abbreviate
6
+
7
+ attr_reader(:fsm)
8
+
9
+ def initialize
10
+ @fsm = PrettyFSM::FSM.new(self, :open)
11
+ @close_timer = PrettyFSM::TimedEvent.new(5)
12
+ @open_timer = PrettyFSM::TimedEvent.new(3)
13
+ end
14
+
15
+ def run
16
+ loop do
17
+ @fsm.advance
18
+ sleep(0.25)
19
+ end
20
+ end
21
+
22
+ def start_open
23
+ puts "Openned door, will close on #{@close_timer.duration} seconds"
24
+ end
25
+
26
+ def while_open
27
+ puts "Waiting to be closed"
28
+ @close_timer.try { start(:close) }
29
+ end
30
+
31
+ def start_close
32
+ puts "Closed door, will close on #{@open_timer.duration} seconds"
33
+ end
34
+
35
+ def while_close
36
+ puts "Waiting to be opened"
37
+ @close_timer.try { start(:open) }
38
+ end
39
+ end
40
+
41
+ Door.new.run
@@ -0,0 +1,55 @@
1
+ module PrettyFSM
2
+ class FSM
3
+ # This will be nil if the FSM hasn't made the initial transition yet.
4
+ attr_reader :state
5
+ attr_accessor :object
6
+
7
+ # _object_ is an instance where all messages regarding transitions and states are sent. States are named with
8
+ # Symbol instances. The prefixes, are the prefixes to the message names that _object_ will receive (if it responds to them).
9
+ def initialize(object, initial_state, while_prefix = 'while_', start_prefix = 'start_', end_prefix = 'end_')
10
+ @object = object
11
+ @while_prefix,@start_prefix,@end_prefix = while_prefix,start_prefix,end_prefix
12
+ @initial_state = initial_state
13
+ @state = nil
14
+ @transitions = Hash.new {|k,v| []}
15
+ if (block_given?) then self.instance_eval(&Proc.new) end
16
+ end
17
+
18
+ # This method should be called periodically. It will act as a timestepper.
19
+ # 'while' methods will be called here.
20
+ def advance
21
+ if (@state.nil?) then start(@initial_state) end
22
+ call_fsm_method(@while_prefix)
23
+
24
+ possible_next_state, = @transitions[@state].find {|state,condition| puts state,condition; @object.send(condition)}
25
+ start(possible_next_state) unless possible_next_state.nil?
26
+ end
27
+
28
+ # Adds a transition definition. Only necessary if you want the FSM to advance itself from a state
29
+ def transition(options)
30
+ @transitions[options[:from]].push([ options[:to], options[:if] ])
31
+ end
32
+
33
+ # Transitions the FSM into the specified state, calling the 'end' and 'start' method, of the old and new states, respectively.
34
+ # Any additional parameter passed to this method will be received by the corresponding 'start' method.
35
+ def start(new_state, *args)
36
+ call_fsm_method(@end_prefix) unless @state.nil?
37
+ @state = new_state
38
+ call_fsm_method(@start_prefix, args)
39
+ end
40
+
41
+ private
42
+ def call_fsm_method(prefix, args = [])
43
+ method_name = (prefix + @state.to_s).to_sym
44
+ if (@object.respond_to?(method_name)) then @object.send(method_name, *args) end
45
+ end
46
+ end
47
+
48
+ # You can use this mixin to abbreviate your calls to FSM#start
49
+ module Abbreviate
50
+ # calls self.fsm.start
51
+ def start(new_state, *args)
52
+ self.fsm.start(new_state, *args)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,28 @@
1
+ module FSM
2
+ # This class is useful to "register" actions to be performed after certain time. You would normally use this
3
+ # in a FSM state, to switch to another state after a while.
4
+ # The notion of 'time' (the _now_ and _duration_ parameters) can be arbitrary, it could be any number for example (as long as it makes sense).
5
+ class TimedEvent
6
+ attr_accessor :duration
7
+
8
+ # Create a TimedEvent that will fire after _duration_ seconds (can be a fractional number) starting from _now_.
9
+ def initialize(duration)
10
+ self.reset
11
+ @duration = duration
12
+ end
13
+
14
+ # Resets the timer, to fire after #duration seconds after _now_
15
+ def reset(now = Time.now)
16
+ @time = now
17
+ end
18
+
19
+ # This method should be called periodically with a block. If #duration seconds have passed since last reset, it will
20
+ # call the passed block.
21
+ def try(now = Time.now)
22
+ if ((now - @time) >= @duration)
23
+ yield
24
+ self.reset
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/pretty-fsm.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'pretty-fsm/fsm'
2
+ require 'pretty-fsm/timed_event'
@@ -0,0 +1,7 @@
1
+ file.reference.fsm-examples=examples
2
+ file.reference.fsm-lib=lib
3
+ javac.classpath=
4
+ main.file=door.rb
5
+ source.encoding=ISO-8859-1
6
+ src.examples.dir=examples
7
+ src.lib.dir=lib
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://www.netbeans.org/ns/project/1">
3
+ <type>org.netbeans.modules.ruby.rubyproject</type>
4
+ <configuration>
5
+ <data xmlns="http://www.netbeans.org/ns/ruby-project/1">
6
+ <name>fsm</name>
7
+ <source-roots>
8
+ <root id="src.lib.dir"/>
9
+ <root id="src.examples.dir"/>
10
+ </source-roots>
11
+ <test-roots/>
12
+ </data>
13
+ </configuration>
14
+ </project>
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{pretty-fsm}
5
+ s.version = "0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["v01d"]
9
+ s.date = %q{2010-03-26}
10
+ s.description = %q{Finite State Machine class with intuitive integration}
11
+ s.email = %q{}
12
+ s.extra_rdoc_files = ["README", "lib/pretty-fsm.rb", "lib/pretty-fsm/fsm.rb", "lib/pretty-fsm/timed_event.rb"]
13
+ s.files = ["Manifest", "README", "Rakefile", "examples/door.rb", "examples/timed_door.rb", "lib/pretty-fsm.rb", "lib/pretty-fsm/fsm.rb", "lib/pretty-fsm/timed_event.rb", "nbproject/project.properties", "nbproject/project.xml", "pretty-fsm.gemspec"]
14
+ s.homepage = %q{http://github.com/v01d/pretty-fsm}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Pretty-fsm", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{pretty-fsm}
18
+ s.rubygems_version = %q{1.3.6}
19
+ s.summary = %q{Finite State Machine class with intuitive integration}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pretty-fsm
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - v01d
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-03-26 00:00:00 -03:00
17
+ default_executable:
18
+ dependencies: []
19
+
20
+ description: Finite State Machine class with intuitive integration
21
+ email: ""
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files:
27
+ - README
28
+ - lib/pretty-fsm.rb
29
+ - lib/pretty-fsm/fsm.rb
30
+ - lib/pretty-fsm/timed_event.rb
31
+ files:
32
+ - Manifest
33
+ - README
34
+ - Rakefile
35
+ - examples/door.rb
36
+ - examples/timed_door.rb
37
+ - lib/pretty-fsm.rb
38
+ - lib/pretty-fsm/fsm.rb
39
+ - lib/pretty-fsm/timed_event.rb
40
+ - nbproject/project.properties
41
+ - nbproject/project.xml
42
+ - pretty-fsm.gemspec
43
+ has_rdoc: true
44
+ homepage: http://github.com/v01d/pretty-fsm
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --line-numbers
50
+ - --inline-source
51
+ - --title
52
+ - Pretty-fsm
53
+ - --main
54
+ - README
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 2
71
+ version: "1.2"
72
+ requirements: []
73
+
74
+ rubyforge_project: pretty-fsm
75
+ rubygems_version: 1.3.6
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Finite State Machine class with intuitive integration
79
+ test_files: []
80
+