pretty-fsm 0.1

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/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
+