baby_bots 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in baby_bots.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012, Justin Hamilton
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ Baby Bots
2
+ =========
3
+
4
+ A small finite-state automata library
5
+ -------------------------------------
6
+
7
+ This is a small finite-state automata library written in Ruby both for a
8
+ project, as well as to teach me how to build gems (I'm not really much of
9
+ a Ruby guy).
10
+
11
+ Let me know of any improviments, thank you!
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/baby_bots.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/baby_bots/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Justin Hamilton"]
6
+ gem.email = ["justinanthonyhamilton@gmail.com"]
7
+ gem.description = %q{A tiny finite-state automata library.}
8
+ gem.summary = %q{While there are many fsa libraries out there, I wanted to implement my own so I could learn how to create a module/gem, as I am not really a Ruby guy and have no idea how.}
9
+ gem.homepage = "https://github.com/jamiltron/BabyBots"
10
+ gem.email = "justinanthonyhamilton@gmail.com"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "baby_bots"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = BabyBots::VERSION
18
+ end
@@ -0,0 +1,98 @@
1
+ module BabyBots
2
+
3
+ class NoSuchStateException < Exception
4
+ end
5
+
6
+ class NoSuchTransitionException < Exception
7
+ end
8
+
9
+ class BabyBot
10
+ attr_accessor :curr, :states, :start
11
+
12
+ def initialize(states={})
13
+ @states = states
14
+ @start = nil
15
+ @curr = nil
16
+ end
17
+
18
+ # add a new state to the state machine
19
+ def add_state(state, start=nil)
20
+ # key on state names to the actual state hash
21
+ @states[state.state] = state
22
+ if start
23
+ @start = state
24
+ @curr = @start
25
+ end
26
+ end
27
+
28
+
29
+ # accepts a hash of hashes consiting of {state => {event => transition, ...} ...}
30
+ # structure, and adds these states to the state machine, assumes first state
31
+ # is the starting state
32
+ def build(table)
33
+ first_state = true
34
+
35
+ # iterate through the provided {state => {event => transition, ...}, ...}
36
+ table.each do |state, state_table|
37
+ temp_state = State.new(state)
38
+
39
+ # iterate through each event and transition, building up the transitions
40
+ state_table.each do |event, transition|
41
+ temp_state.add_transition(event, transition)
42
+ end
43
+
44
+ # finally, add the state to the machine, and since we've already
45
+ # added a start state, clear the first_state flag
46
+ add_state(temp_state, first_state)
47
+ first_state = false
48
+ end
49
+ end
50
+
51
+ # this is the driving function behind the fsa, process
52
+ # will check the current state, doing any processing necessary
53
+ # on the input based on whether or not this
54
+
55
+ def process(event=nil)
56
+ # get the current state
57
+ curr_state = @curr
58
+
59
+ # check if we need to preprocess the event
60
+ if respond_to?("pre_#{@curr.state}")
61
+ event = send("pre_#{@curr.state}", event)
62
+ end
63
+
64
+ next_state = @states[curr.table[event]]
65
+ if next_state.nil?
66
+ next_state = @states[curr.table[:else]]
67
+ end
68
+
69
+ # if the event is nil, and there is no :else clause,
70
+ # throw an exception
71
+ if next_state.nil?
72
+ raise NoSuchTransitionException,
73
+ "No valid transition #{event} for #{@curr.state}"
74
+ end
75
+
76
+ # check if we need to postprocess the event, this will act
77
+ # as the "return" from any state transition (even self-looping transitions)
78
+ if respond_to?("post_#{@curr.state}")
79
+ ret_val = send("post_#{@curr.state}", event)
80
+ end
81
+
82
+
83
+ # actually transition, and make sure such a transition exists
84
+ @curr = next_state
85
+ if @curr.nil?
86
+ raise NoSuchStateException,
87
+ "No valid state #{@curr} for transition #{event} from #{curr_state}"
88
+ end
89
+
90
+ return ret_val
91
+ end
92
+
93
+ def restart
94
+ @curr = @start
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,22 @@
1
+ module BabyBots
2
+
3
+ class State
4
+ attr_reader :state, :table
5
+
6
+ def initialize(state, table={})
7
+ @state = state
8
+ @table = table
9
+ end
10
+
11
+ def add_transition(event, transition, &callback)
12
+ @table[event] = transition
13
+ end
14
+
15
+ # the idea behind build is that you can call multiple
16
+ # :event :transition and the build method
17
+ # will parse them out and add them to state
18
+ def build(*args)
19
+ args.map {|k,v| add_transition(k, v) }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module BabyBots
2
+ VERSION = "0.0.1"
3
+ end
data/lib/baby_bots.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'baby_bots/version'
2
+ require 'baby_bots/baby_bot'
3
+ require 'baby_bots/state'
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: baby_bots
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Justin Hamilton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-30 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: A tiny finite-state automata library.
15
+ email: justinanthonyhamilton@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - Gemfile
22
+ - LICENSE
23
+ - README.md
24
+ - Rakefile
25
+ - baby_bots.gemspec
26
+ - lib/baby_bots.rb
27
+ - lib/baby_bots/baby_bot.rb
28
+ - lib/baby_bots/state.rb
29
+ - lib/baby_bots/version.rb
30
+ homepage: https://github.com/jamiltron/BabyBots
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.8.10
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: While there are many fsa libraries out there, I wanted to implement my own
54
+ so I could learn how to create a module/gem, as I am not really a Ruby guy and have
55
+ no idea how.
56
+ test_files: []