Permalink
Browse files

+ james

  • Loading branch information...
Florian Hanke
Florian Hanke committed Mar 31, 2008
1 parent 7d1b9a6 commit 00ab79dc03c8a15dda0c5f34cfcf7c808415d808
Showing with 49,565 additions and 0 deletions.
  1. +3 −0 config/README
  2. +3 −0 config/names.yml
  3. +19 −0 config/sentences.yml
  4. +8 −0 config/voices.yml
  5. +38 −0 configurator.rb
  6. +8 −0 dialogue.rb
  7. +119 −0 dialogue_extension.rb
  8. +108 −0 dialogue_frontend.rb
  9. +65 −0 dialogue_plugin.rb
  10. BIN dialogues/.DS_Store
  11. +2 −0 dialogues/joke/README
  12. +1 −0 dialogues/joke/init.rb
  13. +40 −0 dialogues/joke/lib/joke_dialogue.rb
  14. +1 −0 dialogues/phonebook/init.rb
  15. +28 −0 dialogues/phonebook/lib/phonebook.rb
  16. +115 −0 dialogues/phonebook/lib/phonebook_dialogue.rb
  17. +53 −0 dialogues/phonebook/test/test_phonebook.rb
  18. +1 −0 dialogues/quote/README
  19. +1 −0 dialogues/quote/init.rb
  20. +42 −0 dialogues/quote/lib/quote_dialogue.rb
  21. +56 −0 dialogues/quote/lib/quote_of_the_day.rb
  22. +9 −0 dialogues/quote/test/test_quote_of_the_day.rb
  23. BIN dialogues/sbb/.DS_Store
  24. +1 −0 dialogues/sbb/README
  25. +1 −0 dialogues/sbb/init.rb
  26. +96 −0 dialogues/sbb/lib/hpricot_finder.rb
  27. +15 −0 dialogues/sbb/lib/sbb.rb
  28. +174 −0 dialogues/sbb/lib/sbb_dialogue.rb
  29. +59 −0 dialogues/sbb/lib/sbb_finder.rb
  30. +53 −0 dialogues/sbb/lib/scrapi_finder.rb
  31. +57 −0 dialogues/sbb/lib/scrubyt_finder.rb
  32. +1,419 −0 dialogues/sbb/lib/test.html
  33. +1,371 −0 dialogues/sbb/test/test.html
  34. +40 −0 dialogues/sbb/test/test_sbb.rb
  35. +1 −0 dialogues/time/README
  36. +1 −0 dialogues/time/init.rb
  37. +28 −0 dialogues/time/lib/time_dialogue.rb
  38. +41 −0 initializer.rb
  39. +247 −0 main_dialogue.rb
  40. BIN rubyscript2exe/.DS_Store
  41. +375 −0 rubyscript2exe/CHANGELOG
  42. +15 −0 rubyscript2exe/LICENSE
  43. +22 −0 rubyscript2exe/README
  44. +1 −0 rubyscript2exe/SUMMARY
  45. +1 −0 rubyscript2exe/VERSION
  46. BIN rubyscript2exe/eee.ico
  47. BIN rubyscript2exe/eee.o
  48. +1,143 −0 rubyscript2exe/eee.pas
  49. +1 −0 rubyscript2exe/eee.rc
  50. BIN rubyscript2exe/eee_darwin
  51. +96 −0 rubyscript2exe/ev/dependencies.rb
  52. +216 −0 rubyscript2exe/ev/ftools.rb
  53. +134 −0 rubyscript2exe/ev/oldandnewlocation.rb
  54. +3 −0 rubyscript2exe/hello.rb
  55. +371 −0 rubyscript2exe/init.rb
  56. +148 −0 rubyscript2exe/require2lib.rb
  57. +37,029 −0 rubyscript2exe/rubyscript2exe.rb
  58. +4,279 −0 rubyscript2exe/tar2rubyscript.rb
  59. +1,332 −0 test.html
  60. +15 −0 test/dummy_frontend.rb
  61. +58 −0 test/test_dialogue.rb
  62. +2 −0 test/test_helper.rb
View
@@ -0,0 +1,3 @@
+This folder contains configuration files for james itself.
+
+The files are in YAML format (http://de.wikipedia.org/wiki/YAML).
View
@@ -0,0 +1,3 @@
+# names for the two voices
+female: jamie
+male: james
View
@@ -0,0 +1,19 @@
+# with this file it is possible to configure your james's core
+# commands are denoted with an exclamation mark
+# it is not possible to use multiple command words
+sleep!: sleep
+return from dialogue!: thank you
+# when james ... he says one of ...
+wakes up:
+ - yes?
+ - sir?
+ - ready!
+ - ok!
+ - tell me!
+ - yes, sir?
+ - your wish is my command.
+ - at your service.
+goes to sleep:
+ - good night!
+ - good bye!
+ - hasta la vista, baby!
View
@@ -0,0 +1,8 @@
+# Commented voices are Apple built-in voices. Can be changed by replacing the last part e.g.'Vicki' with e.g.'Laura'
+# much better female voice from iVox:
+# female: com.acapela.iVox.voice.iVoxHeather22k
+# much better male voice from iVox:
+# male: com.acapela.iVox.voice.iVoxRyan22k
+female: com.apple.speech.synthesis.voice.Vicki
+# male: com.apple.speech.synthesis.voice.Bruce
+male: com.apple.speech.synthesis.voice.Alex
View
@@ -0,0 +1,38 @@
+# TODO all
+
+# configures
+class Configurator
+ def self.configure
+
+ end
+end
+
+require 'osx/cocoa'
+
+...
+
+def initialize
+ # get and configure a recognizer interface
+ @recognizer = OSX::NSSpeechRecognizer.alloc.init
+ @recognizer.setDelegate(self)
+ @recognizer.startListening
+ # get a synthesizer interface
+ @synthesizer = OSX::NSSpeechSynthesizer.alloc.init
+end
+
+# callback method from the speech interface
+def speechRecognizer_didRecognizeCommand( sender, command )
+ # do something with the command
+ # command needs to be converted to a proper ruby string: command.to_s
+end
+
+def speak(text)
+ # say something using the speech synthesizer
+ @synthesizer.startSpeakingString(text)
+end
+
+state :to, {
+ 'back' => :from,
+ 'next train' => :result,
+ 'nowhere' => :result
+}.merge(CITIES)
View
@@ -0,0 +1,8 @@
+class Dialogue
+
+ # choose one reply randomly from the given replies
+ def random_reply(replies)
+ replies[rand(replies.size)]
+ end
+
+end
View
@@ -0,0 +1,119 @@
+# require 'cocoa'
+
+# TODO make ['HB','berne','geneva'] => :from possible using the splat operator
+# add ability to chain dialogues a la chain_dialogue :state, <dialogue_name>
+
+# superclass for dialogue modules
+# dialogues move along the moves
+# if a state is entered, enter_#{state_name} is called
+# if a state is exited, exit_#{state_name} is called
+class DialogueExtension < Dialogue
+
+ attr_reader :state
+
+ alias :old_initialize :initialize
+
+ # every subclass of this class automatically has its state set to :entry on creation
+ # def initialize(*args)
+ # puts "Resetting ", self.name, "\n"
+ # reset
+ # old_initialize(*args)
+ # end
+
+ # # automatically adds a hook phrase
+ # # meaning: adds a move from :awake to this hook word
+ # # and also a method
+ def initialize
+ # reset
+ end
+ #
+ # # TODO improve this such that reset doesn't need to be called in each initializer!
+ def reset
+ @state = :entry
+ end
+
+ # TODO think about saying something after each method call though like this it is kept simple which is good
+ def hear(phrase)
+ # if next state
+ return nil unless next_state(phrase)
+ # call exit method
+ send("exit_#{@state}".intern, phrase) if respond_to?("exit_#{@state}")
+ # TODO say(response)
+ # set actual state
+ @state = self.next_state(phrase)
+ # call entry method
+ send("enter_#{@state}".intern) if respond_to?("enter_#{@state}")
+ end
+
+ # next possible phrases
+ # TODO splat
+ def expects
+ self.class.moves[@state].keys
+ end
+
+ def next_state(phrase)
+ self.class.moves[@state][phrase] if self.class.moves[@state]
+ end
+
+ # returns the possible states of this dialogue
+ def self.possible_states
+ self.moves.keys
+ end
+
+ # metaprog
+
+ # hook words - these define when this dialogue is entered
+ # adds a hooks method
+ # TODO get hooks from yaml file
+ def self.hook_words(*hooks)
+ self.class_eval do
+ # set entry state correctly
+ entry = {}
+ hooks.each do |hook|
+ entry[hook] = self.initial
+ end
+ # add moves class variable
+ class <<self
+ attr_accessor :moves
+ end
+ self.moves ||= {}
+ self.moves[:entry] = entry
+ # define an instance method
+ define_method(:hooks) do
+ hooks
+ end
+ end
+ end
+
+ # initial state
+ def self.initial_state(initial)
+ self.class_eval do
+ # add accessor for
+ class <<self
+ attr_accessor :initial
+ end
+ self.initial = initial
+ end
+ end
+
+ # state definitions like
+ # state :name, { moves }
+ def self.state(name, moves)
+ self.class_eval do
+ self.moves ||= {}
+ self.moves[name] ||= {}
+ # split arrays here instead of handling later specifically
+ # can change the implementation later if needed
+ moves.each do |words,state|
+ words.each do |word|
+ self.moves[name][word] = state
+ end
+ end
+ #
+ # self.moves[name] = moves
+ # puts "moves for #{self.name} are #{self.moves.inspect}"
+ end
+ # puts "#{self.name} === #{self.moves.inspect}"
+ end
+
+end
View
@@ -0,0 +1,108 @@
+require 'osx/cocoa'
+require 'main_dialogue'
+
+# TODO move some stuff in the dialogue
+# TODO extract cocoa connection
+# TODO implement callback
+
+# debug
+USE_TEXTUAL_INTERFACE = false
+
+class DialogueFrontend
+
+ attr_reader :dialogue
+
+ def initialize
+ # load voices
+ load_voices
+
+ # get a dialogue
+ @dialogue = MainDialogue.new(self)
+
+ # get and configure a recognizer interface
+ start_recognizer
+
+ # get a synthesizer interface
+ start_synthesizer
+
+ # default voice
+ male
+ end
+
+ # callback method from the speech interface
+ def speechRecognizer_didRecognizeCommand( sender, command )
+ command = command.to_s
+ # call the dialogue system
+ @dialogue.hear(command)
+ # set actual commands
+ self.commands = @dialogue.expects
+ end
+
+ # callback method from dialogue
+ def say(text)
+ @synthesizer.startSpeakingString(text)
+ end
+
+ # callback from dialogue
+ def male
+ self.voice = @male_voice
+ end
+
+ # callback from dialogue
+ def female
+ self.voice = @female_voice
+ end
+
+ # wrapper for the cocoa setCommands
+ def commands=(commands)
+ @recognizer.setCommands(commands)
+ puts "expects: #{commands.join(', ')}"
+ end
+
+ private
+
+ # specialized setter for voice
+ def voice=(voice)
+ @synthesizer.setVoice(voice)
+ end
+
+ # start recognizing words
+ def start_recognizer
+ @recognizer = OSX::NSSpeechRecognizer.alloc.init
+ @recognizer.setBlocksOtherRecognizers(true)
+ @recognizer.setListensInForegroundOnly(false)
+ @recognizer.setDelegate(self)
+ self.commands = @dialogue.expects
+ @recognizer.startListening
+ end
+
+ # start speaking
+ def start_synthesizer
+ @synthesizer = OSX::NSSpeechSynthesizer.alloc.init
+ end
+
+ # load voices from yaml
+ def load_voices
+ yaml_voices = ''
+ File.open('config/voices.yml') do |f| yaml_voices << f.read end
+ voices = YAML.load(yaml_voices)
+ @male_voice = voices['male']
+ @female_voice = voices['female']
+ end
+
+end
+
+controller = DialogueFrontend.new
+
+# code to use a textual interface
+while USE_TEXTUAL_INTERFACE
+ exit_words = ['quit','exit']
+ puts "'#{exit_words.join("' or '")}' to quit. Expects: #{controller.dialogue.expects.join(', ')}"
+ input = gets.chomp
+ if exit_words.include?(input)
+ break
+ end
+ controller.dialogue.hear(input)
+end
+
+OSX::NSApplication.sharedApplication.run
View
@@ -0,0 +1,65 @@
+require 'rubycocoa'
+
+# superclass for dialogue modules
+# dialogues move along the moves
+# if a state is entered, enter_#{state_name} is called
+# if a state is exited, exit_#{state_name} is called
+class DialoguePlugin
+
+ # automatically adds a hook phrase
+ # meaning: adds a move from :awake to this hook word
+ # and also a method
+ def initialize
+ # actual state in this module
+ @state = nil
+ # defines possible moves from one state to another
+ @moves = {
+
+ }
+ end
+
+ # returns the possible states of this dialogue
+ def possible_states
+ @moves.keys
+ end
+
+ # next possible phrases
+ def expects_phrases
+ @moves[@state].keys
+ end
+
+ def next_state(phrase)
+ @moves[@state][phrase]
+ end
+
+ def hear(phrase)
+ # if next state
+ return unless next_state(phrase)
+ # call exit method
+ response = send("exit_#{@state}".intern, phrase)
+ say response
+ # set actual state
+ @state = next_state(phrase)
+ # call entry method
+ response = send("enter_#{@state}")
+ say response
+ end
+
+ def say(text)
+ # TODO blah
+ end
+
+ # hook words - these define when this dialogue is entered
+ def hook_words(names = nil)
+ names.each do |name|
+ # TODO
+ end
+ end
+
+ def initial_state(initial)
+ define_method(:reset) do
+ @state = initial
+ end
+ end
+
+end
View
Binary file not shown.
View
@@ -0,0 +1,2 @@
+TODO: load the jokes from somewhere
+With this dialogue part, james can tell jokes!
View
@@ -0,0 +1 @@
+require 'joke_dialogue'
Oops, something went wrong.

0 comments on commit 00ab79d

Please sign in to comment.