public
Description: An extensible bot for the Campfire web-based chat system #crc
Homepage:
Clone URL: git://github.com/timriley/campfire-bot.git
get started with a different, simpler markov implementation
timriley (author)
Thu Oct 30 06:45:21 -0700 2008
commit  372567b253437bbc8c55d547bfc143f12c602587
tree    cf13287516487762fb1fa57e4764da949734e572
parent  0f6e12195b145b9eb2d44d1148f698454b61e704
...
1
2
3
 
4
5
 
6
7
8
9
10
11
12
 
 
13
14
15
16
17
18
19
20
 
 
21
22
23
...
29
30
31
32
33
34
35
36
37
38
39
40
 
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 
 
 
 
 
 
 
 
 
55
56
57
58
59
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
62
63
64
 
65
66
 
67
68
69
70
71
72
73
74
75
76
77
78
79
 
 
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
1
2
 
3
4
 
5
6
7
8
9
10
11
 
12
13
14
15
 
 
 
 
 
 
16
17
18
19
20
...
26
27
28
 
 
29
30
31
32
33
34
 
35
36
37
38
39
40
41
 
 
 
 
 
 
 
 
42
43
44
45
46
47
48
49
50
51
52
53
 
 
 
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 
 
 
79
80
 
81
82
83
 
 
 
 
 
 
 
 
 
 
 
84
85
86
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
89
90
0
@@ -1,23 +1,20 @@
0
 class Boop < CampfireBot::Plugin
0
   
0
-  # Markov chain implementation courtesy of http://rubyquiz.com/quiz74.html
0
+  # Markov chain implementation courtesy of http://blog.segment7.net/articles/2006/02/25/markov-chain
0
   
0
-  on_message /.*/,                :build_chains
0
+  on_message /.*/,                :listen
0
   on_command 'speak',             :random_chatter
0
   on_command 'prime_chains',      :load_transcripts
0
   
0
   on_command 'test',              :debug
0
   
0
   def initialize
0
-    @words = Hash.new
0
+    @phrases    = Hash.new { |hash, key| hash[key] = [] } # phrase => next-word possibilities
0
+    @word_count = 0
0
   end
0
   
0
-  def debug(msg)
0
-    p @words
0
-  end
0
-  
0
-  def build_chains(msg)
0
-    add_line(msg[:message])
0
+  def listen(msg)
0
+    add_words(msg[:message])
0
   end
0
   
0
   def random_chatter(msg)
0
@@ -29,75 +26,65 @@ class Boop < CampfireBot::Plugin
0
     
0
   end
0
   
0
-  # TODO strip tags, ignore images.
0
-  
0
   def load_transcripts(msg)
0
     speak("Filling my brain with transcripts...")
0
     bot.room.available_transcripts.each do |date|
0
       transcript = bot.room.transcript(date)
0
       transcript.each do |message|
0
         filtered_text = strip_messages(message)
0
-        add_line(filtered_text.gsub(/([^\.])$/, '\1.')) unless filtered_text.blank?
0
+        add_words(filtered_text.gsub(/([^\.])$/, '\1.')) unless filtered_text.blank?
0
         puts filtered_text.gsub(/([^\.])$/, '\1.') unless filtered_text.blank?
0
       end
0
     end
0
     speak("Primed!")
0
   end
0
   
0
-  protected
0
-  
0
-  # Building the chains
0
-  
0
-  def add_line(text)
0
-    wordlist = text.split
0
-    wordlist.each_with_index do |word, index|
0
-      add_word(word, wordlist[index + 1]) if index <= wordlist.size - 2
0
+  private
0
+    
0
+  def add_line(line)
0
+    words        = line.scan(/\S+/))
0
+    @word_count += words.length
0
+    
0
+    words.each_with_index do |word, index|
0
+      phrase = words[index, phrase_length]             # current phrase
0
+      @phrases[phrase] << words[index + phrase_length] # next possibility
0
     end
0
   end
0
   
0
-  def add_word(word, next_word)
0
-    @words[word] = Hash.new(0) if !@words[word]
0
-    @words[word][next_word] += 1
0
+  def generate_line
0
+    # our seed phrase
0
+    # phrase = words[0, phrase_length]
0
+    phrase = random_word
0
+
0
+    output = []
0
+
0
+    @max_words.times do
0
+      # grab all possibilities for our state
0
+      options = phrases[phrase]
0
+
0
+      # add the first word to our output and discard
0
+      output << phrase.shift
0
+
0
+      # select at random and add it to our phrase
0
+      phrase.push options[rand(options.length)]
0
+
0
+      # the last phrase of the input text will map to an empty array of
0
+      # possibilities so exit cleanly.
0
+      break if phrase.compact.empty? # all out of words
0
+    end
0
+
0
+    # print out our output
0
+    puts output.join(' ')
0
   end
0
-  
0
-  # Fetching from the chains
0
-  
0
+    
0
   def random_word
0
-    @words.keys.rand
0
+    @phrases.keys.rand.first
0
   end
0
   
0
-  def get_word(word)
0
-    return "" if !@words[word]
0
-    followers = @words[word]
0
-    sum = followers.inject(0) {|sum,kv| sum += kv[1]}
0
-    random = rand(sum)+1
0
-    partial_sum = 0
0
-    next_word = followers.find do |word, count|
0
-      partial_sum += count
0
-      partial_sum >= random
0
-    end.first
0
-    next_word
0
+  def phrase_length
0
+    1
0
   end
0
   
0
-  # Composing sentences
0
-  
0
-  def get_sentences(count = 1, start_word = nil)
0
-    puts "get_sentences"
0
-    
0
-    word      = start_word || random_word
0
-    
0
-    puts "starting word is #{word}"
0
-    
0
-    sentences = ''
0
-    until sentences.count('.') == count
0
-      sentences << word << ' '
0
-      word = get_word(word)
0
-    end
0
-    sentences
0
-  end
0
-  
0
-  # Utility
0
-  
0
   def strip_messages(msg)
0
     str = msg[:message].to_s
0
     

Comments