james 0.1.1-universal-darwin-10 → 0.2.0-universal-darwin-10

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.
@@ -2,18 +2,28 @@ module James
2
2
 
3
3
  class State
4
4
 
5
- attr_reader :transitions
5
+ # Transitions are internal transitions & external transitions.
6
+ #
7
+ def transitions
8
+ @transitions
9
+ end
6
10
 
7
- # Returns all possible phrases that lead
8
- # away from this state.
9
11
  #
10
- def phrases
12
+ #
13
+ def expects
11
14
  transitions.keys
12
15
  end
13
16
 
17
+ #
18
+ #
19
+ def internal_expects
20
+ transitions.select { |phrase, target| target.respond_to?(:to_sym) || target == self.context }.keys
21
+ end
22
+
23
+
14
24
  # Returns the next state for the given phrase.
15
25
  #
16
- # It accesses the context (aka Dialog(ue)) to get a full object state.
26
+ # It accesses the context (aka Dialog) to get a full object state.
17
27
  #
18
28
  # If it is a Symbol, James will try to get the real state.
19
29
  # If not, it will just return it (a State already, or lambda).
@@ -23,15 +33,26 @@ module James
23
33
  state.respond_to?(:id2name) ? context.state_for(state) : state
24
34
  end
25
35
 
26
- def __into__
27
- @into_block && context.instance_eval(&@into_block)
28
- end
29
- def __exit__
30
- @exit_block && context.instance_eval(&@exit_block)
31
- end
32
- def __transition__ &block
33
- context.instance_eval &block
34
- end
36
+ # The naughty privates.
37
+ #
38
+
39
+ # Called by the visitor visiting this state.
40
+ #
41
+ def __into__
42
+ @into_block && context.instance_eval(&@into_block)
43
+ end
44
+
45
+ # Called by the visitor visiting this state.
46
+ #
47
+ def __exit__
48
+ @exit_block && context.instance_eval(&@exit_block)
49
+ end
50
+
51
+ # Called by the visitor visiting this state.
52
+ #
53
+ def __transition__ &block
54
+ context.instance_eval &block
55
+ end
35
56
 
36
57
  end
37
58
 
data/lib/james.rb CHANGED
@@ -3,8 +3,10 @@ module James; end
3
3
  require File.expand_path '../james/state_api', __FILE__
4
4
  require File.expand_path '../james/state_internals', __FILE__
5
5
 
6
- require File.expand_path '../james/visitor', __FILE__
7
- require File.expand_path '../james/visitors', __FILE__
6
+ require File.expand_path '../james/markers/marker', __FILE__
7
+ require File.expand_path '../james/markers/current', __FILE__
8
+ require File.expand_path '../james/markers/memory', __FILE__
9
+ require File.expand_path '../james/conversation', __FILE__
8
10
 
9
11
  require File.expand_path '../james/dialog_api', __FILE__
10
12
  require File.expand_path '../james/dialog_internals', __FILE__
@@ -30,13 +32,11 @@ module James
30
32
  # If called twice or more, will just add more dialogs.
31
33
  #
32
34
  def self.use *dialogs
33
- dialogs.each { |dialog| controller.add_dialog dialog }
35
+ dialogs.each { |dialog| controller << dialog}
34
36
  end
35
37
 
36
38
  # Start listening.
37
39
  #
38
- # Will not listen again if already listening.
39
- #
40
40
  def self.listen options
41
41
  controller.listen options
42
42
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: james
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.2.0
6
6
  platform: universal-darwin-10
7
7
  authors:
8
8
  - Florian Hanke
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-29 00:00:00 +10:00
12
+ date: 2011-06-08 00:00:00 +10:00
13
13
  default_executable: james
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -38,6 +38,7 @@ extra_rdoc_files: []
38
38
  files:
39
39
  - lib/james/builtin/core_dialog.rb
40
40
  - lib/james/controller.rb
41
+ - lib/james/conversation.rb
41
42
  - lib/james/dialog_api.rb
42
43
  - lib/james/dialog_internals.rb
43
44
  - lib/james/dialogs.rb
@@ -45,23 +46,15 @@ files:
45
46
  - lib/james/inputs/audio.rb
46
47
  - lib/james/inputs/base.rb
47
48
  - lib/james/inputs/terminal.rb
49
+ - lib/james/markers/current.rb
50
+ - lib/james/markers/marker.rb
51
+ - lib/james/markers/memory.rb
48
52
  - lib/james/outputs/audio.rb
49
53
  - lib/james/outputs/terminal.rb
50
54
  - lib/james/state_api.rb
51
55
  - lib/james/state_internals.rb
52
- - lib/james/visitor.rb
53
- - lib/james/visitors.rb
54
56
  - lib/james.rb
55
57
  - aux/james/cli.rb
56
- - spec/aux/james/cli_spec.rb
57
- - spec/integration/test_dialogue_spec.rb
58
- - spec/lib/james/controller_spec.rb
59
- - spec/lib/james/dialog_spec.rb
60
- - spec/lib/james/inputs/audio_spec.rb
61
- - spec/lib/james/inputs/terminal_spec.rb
62
- - spec/lib/james/state_spec.rb
63
- - spec/lib/james/visitor_spec.rb
64
- - spec/lib/james/visitors_spec.rb
65
58
  - bin/james
66
59
  has_rdoc: true
67
60
  homepage: http://floere.github.com/james
@@ -88,13 +81,4 @@ rubygems_version: 1.4.2
88
81
  signing_key:
89
82
  specification_version: 3
90
83
  summary: 'James: Modular Electronic Butler with modular Dialogs.'
91
- test_files:
92
- - spec/aux/james/cli_spec.rb
93
- - spec/integration/test_dialogue_spec.rb
94
- - spec/lib/james/controller_spec.rb
95
- - spec/lib/james/dialog_spec.rb
96
- - spec/lib/james/inputs/audio_spec.rb
97
- - spec/lib/james/inputs/terminal_spec.rb
98
- - spec/lib/james/state_spec.rb
99
- - spec/lib/james/visitor_spec.rb
100
- - spec/lib/james/visitors_spec.rb
84
+ test_files: []
data/lib/james/visitor.rb DELETED
@@ -1,80 +0,0 @@
1
- module James
2
-
3
- # The visitor knows where in the conversation we are.
4
- #
5
- # It also remembers where it has to go back to if
6
- # too much time passes without input.
7
- #
8
- # Note: A visitor should generally be very stupid.
9
- #
10
- class Visitor
11
-
12
- attr_reader :initial, :timer
13
- attr_accessor :current
14
-
15
- # Pass in an initial state to start from.
16
- #
17
- def initialize initial
18
- @current = initial
19
-
20
- @initial = initial
21
- end
22
-
23
- # Resets the current state back to the initial.
24
- #
25
- def reset
26
- self.current = initial
27
- end
28
-
29
- # We hear a phrase.
30
- #
31
- # Also used to start the whole process.
32
- #
33
- def enter
34
- result = current.__into__
35
- yield result if result && block_given?
36
- result
37
- end
38
- def exit
39
- result = current.__exit__
40
- yield result if result && block_given?
41
- result
42
- end
43
- def transition phrase
44
- state_or_lambda = current.next_for phrase
45
- if state_or_lambda.respond_to?(:call)
46
- current.__transition__ &state_or_lambda # Don't transition.
47
- else
48
- self.current = state_or_lambda
49
- end
50
- end
51
- def check
52
- reset && yield("Whoops. That led nowhere. Perhaps you didn't define the target state?") unless self.current
53
- end
54
- def hear phrase, &block
55
- return unless hears? phrase
56
- exit_text = exit &block
57
- transition phrase
58
- check &block
59
- into_text = enter &block
60
- exit_text || into_text
61
- end
62
- def hears? phrase
63
- expects.include? phrase
64
- end
65
- def expects
66
- current.phrases
67
- end
68
- # Does the current state allow penetration into another dialog?
69
- #
70
- def chainable?
71
- current.chainable?
72
- end
73
-
74
- def to_s
75
- "#{self.class.name}(#{initial}, current: #{current})"
76
- end
77
-
78
- end
79
-
80
- end
@@ -1,62 +0,0 @@
1
- module James
2
-
3
- # The visitors class has a number of visitors, whose
4
- # dialogs are visited in order of preference.
5
- #
6
- # Why?
7
- # Discussions have multiple points where they can be.
8
- # (Politics, then this joke, then back again, finally "Oh, bye I have to go!")
9
- #
10
- # In James, though, it is much simpler.
11
- # We just have a visitor in an entry scenario
12
- # (James!, Sleep, Wake up, Something completely different)
13
- # and one in any specific user-given scenario.
14
- #
15
- # Visitors is a proxy object for visitors.
16
- #
17
- class Visitors
18
-
19
- attr_reader :visitors
20
-
21
- def initialize *visitors
22
- @visitors = visitors
23
- end
24
-
25
- # Hear tries all visitors in order
26
- # until one hears a phrase he knows.
27
- #
28
- # After that, all remaining visitors are reset.
29
- #
30
- def hear phrase, &block
31
- enumerator = visitors.dup
32
-
33
- while visitor = enumerator.shift
34
- visitor.hear phrase, &block and break
35
- end
36
-
37
- enumerator.each do |visitor|
38
- visitor.reset
39
- end
40
- end
41
-
42
- # Enter enters the first visitor.
43
- #
44
- def enter
45
- visitors.first.enter
46
- end
47
-
48
- # Simply returns the sum of what phrases all dialogs do expect, front-to-back.
49
- #
50
- # Stops as soon as a visitor is not in a chainable state anymore.
51
- #
52
- def expects
53
- visitors.inject([]) do |expects, visitor|
54
- total = visitor.expects + expects
55
- break total unless visitor.chainable?
56
- total
57
- end
58
- end
59
-
60
- end
61
-
62
- end
@@ -1,19 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../../aux/james/cli', __FILE__
4
-
5
- describe James::CLI do
6
-
7
- before(:each) do
8
- Dir.stub! :[] => ['test_dialog.rb', 'test_dialog.rb', 'test/test_dialog.rb']
9
- end
10
-
11
- let(:cli) { James::CLI.new }
12
-
13
- describe 'find_dialogs' do
14
- it 'returns the right ones' do
15
- cli.find_dialogs.should == ['test_dialog.rb', 'test_dialog.rb', 'test/test_dialog.rb']
16
- end
17
- end
18
-
19
- end
@@ -1,67 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../lib/james', __FILE__
4
-
5
- describe 'TestDialog' do
6
-
7
- context 'unit' do
8
- let(:dialog) do
9
-
10
- Class.new do
11
- include James::Dialog
12
-
13
- hear ['test1', 'test2'] => :first
14
-
15
- state :first do
16
- hear 'go' => :second, 'stay' => :first
17
- end
18
-
19
- state :second do
20
- hear 'go' => :third, 'back' => :first
21
- end
22
- end.new
23
-
24
- end
25
- let(:visitor) do
26
- James::Visitor.new dialog.state_for(:first)
27
- end
28
-
29
- describe "integration" do
30
- it 'works correctly' do
31
- visitor.current.name.should == :first
32
- visitor.hear('go') {}
33
- visitor.current.name.should == :second
34
- visitor.hear('back') {}
35
- visitor.current.name.should == :first
36
- visitor.hear('stay') {}
37
- visitor.current.name.should == :first
38
- end
39
- end
40
- end
41
-
42
- # context 'integration' do
43
- # let(:dialog) do
44
- # dialog = Class.new do
45
- # include James::Dialog
46
- #
47
- # hear ['test1', 'test2'] => :first
48
- # state :first do
49
- # hear 'go' => :second, 'stay' => :first
50
- # end
51
- # state :second do
52
- # hear 'go' => :third, 'back' => :first
53
- # end
54
- # end.new
55
- # end
56
- # it 'works correctly' do
57
- # dialog.state.name.should == :awake
58
- # dialog.hear 'sleep'
59
- # dialog.state.name.should == :sleeping
60
- # end
61
- # it 'delegates correctly' do
62
- # dialog.state.name.should == :awake
63
- # dialog.hear 'test1'
64
- # end
65
- # end
66
-
67
- end
@@ -1,35 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../../lib/james/dialog_api', __FILE__
4
- require File.expand_path '../../../../lib/james/dialog_internals', __FILE__
5
- require File.expand_path '../../../../lib/james/builtin/core_dialog', __FILE__
6
- require File.expand_path '../../../../lib/james/visitors', __FILE__
7
- require File.expand_path '../../../../lib/james/visitor', __FILE__
8
- require File.expand_path '../../../../lib/james/state_api', __FILE__
9
- require File.expand_path '../../../../lib/james/dialogs', __FILE__
10
- require File.expand_path '../../../../lib/james/inputs/base', __FILE__
11
- require File.expand_path '../../../../lib/james/inputs/terminal', __FILE__
12
- require File.expand_path '../../../../lib/james/inputs/audio', __FILE__
13
- require File.expand_path '../../../../lib/james/controller', __FILE__
14
-
15
- describe James::Controller do
16
-
17
- let(:controller) { described_class.new }
18
-
19
- describe 'listening?' do
20
- it 'is correct' do
21
- controller.listening?.should == false
22
- end
23
- end
24
- describe 'expects' do
25
- it 'delegates' do
26
- visitor = stub! :visitor
27
- controller.stub! :visitor => visitor
28
-
29
- visitor.should_receive(:expects).once.with()
30
-
31
- controller.expects
32
- end
33
- end
34
-
35
- end
@@ -1,90 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../../lib/james', __FILE__
4
- require File.expand_path '../../../../lib/james/state_api', __FILE__
5
- require File.expand_path '../../../../lib/james/dialog_api', __FILE__
6
- require File.expand_path '../../../../lib/james/dialog_internals', __FILE__
7
- require File.expand_path '../../../../lib/james/builtin/core_dialog', __FILE__
8
- require File.expand_path '../../../../lib/james/dialogs', __FILE__
9
-
10
- describe James::Dialog do
11
-
12
- context 'units' do
13
- let(:dialog) do
14
- James.use_dialog do
15
-
16
- hear 'something' => :first
17
-
18
- state :first do
19
- hear 'something else' => :second
20
- into {}
21
- exit {}
22
- end
23
-
24
- state :second do
25
- hear 'yet something else' => :first
26
- into {}
27
- exit {}
28
- end
29
-
30
- end
31
- end
32
- describe 'state_for' do
33
- it 'delegates to the class, adding itself' do
34
- new_dialog = dialog.new
35
- dialog.should_receive(:state_for).once.with :some_name, new_dialog
36
-
37
- new_dialog.state_for :some_name
38
- end
39
- it 'returns nil on not found' do
40
- dialog.new.state_for(:nonexistent).should == nil
41
- end
42
- end
43
- end
44
-
45
- describe 'hear with lambda' do
46
- let(:dialog) do
47
- class Test
48
- include James::Dialog
49
-
50
- def initialize
51
- @bla = 'some bla'
52
- end
53
-
54
- state :test do
55
- hear 'bla' => ->(){ @bla }
56
- end
57
- end
58
- Test.new
59
- end
60
- it "is instance eval'd" do
61
- test_state = dialog.state_for :test
62
- test_state.hear 'bla' do |result|
63
- result.should == 'some bla'
64
- end
65
- end
66
- end
67
-
68
- describe 'initialization' do
69
- it 'can be included' do
70
- expect do
71
- class Test
72
- include James::Dialog
73
-
74
- hear 'something' => :some_state
75
- end
76
- end.to_not raise_error
77
- end
78
-
79
- it 'can be defined' do
80
- expect do
81
- James.dialog do
82
-
83
- hear 'something' => :some_state
84
-
85
- end
86
- end.to_not raise_error
87
- end
88
- end
89
-
90
- end
@@ -1,18 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
4
- require File.expand_path '../../../../../lib/james/inputs/audio', __FILE__
5
-
6
- describe James::Inputs::Audio do
7
-
8
- let(:input) { described_class.new }
9
-
10
- describe 'speechRecognizer' do
11
- it 'does something' do
12
- sender = stub :sender
13
-
14
- input.speechRecognizer sender
15
- end
16
- end
17
-
18
- end
@@ -1,12 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
4
- require File.expand_path '../../../../../lib/james/inputs/terminal', __FILE__
5
-
6
- describe James::Inputs::Terminal do
7
-
8
- let(:input) { described_class.new }
9
-
10
-
11
-
12
- end