programr 0.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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +64 -0
- data/Rakefile +2 -0
- data/conf/readOnlyTags.yaml +37 -0
- data/lib/programr.rb +5 -0
- data/lib/programr/aiml_elements.rb +352 -0
- data/lib/programr/aiml_parser.rb +269 -0
- data/lib/programr/environment.rb +75 -0
- data/lib/programr/facade.rb +65 -0
- data/lib/programr/graph_master.rb +110 -0
- data/lib/programr/history.rb +82 -0
- data/lib/programr/utils.rb +30 -0
- data/lib/programr/version.rb +3 -0
- data/programr.gemspec +17 -0
- data/test/data/1.aiml +125 -0
- data/test/data/facade.aiml +233 -0
- data/test/data/mixed/dir/badfile +1 -0
- data/test/data/mixed/dir/in_dir.aiml +9 -0
- data/test/data/mixed/dir/subdir/in_sub_dir.aiml +17 -0
- data/test/data/mixed/single.aiml +9 -0
- data/test/data/test.aiml +44 -0
- data/test/test_facade.rb +67 -0
- data/test/test_utils.rb +18 -0
- metadata +81 -0
| @@ -0,0 +1,269 @@ | |
| 1 | 
            +
            require 'rexml/parsers/sax2parser'
         | 
| 2 | 
            +
            require 'programr/aiml_elements'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            # gli accenti nel file di input vengono trasformati in ' !!!
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            module  ProgramR
         | 
| 7 | 
            +
            class AimlParser
         | 
| 8 | 
            +
              def initialize(learner); @learner = learner end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def parse(aiml)
         | 
| 11 | 
            +
                @parser = REXML::Parsers::SAX2Parser.new(aiml)
         | 
| 12 | 
            +
                category         = nil
         | 
| 13 | 
            +
                openLabels       = []
         | 
| 14 | 
            +
                patternIsOpen    = false
         | 
| 15 | 
            +
                thatIsOpen       = false
         | 
| 16 | 
            +
                currentSetLabel  = nil
         | 
| 17 | 
            +
                currentCondition = nil
         | 
| 18 | 
            +
                currentSrai      = nil
         | 
| 19 | 
            +
                currentGender    = nil
         | 
| 20 | 
            +
                currentPerson    = nil
         | 
| 21 | 
            +
                currentPerson2   = nil
         | 
| 22 | 
            +
                currentTopic     = nil
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                @parser.listen(%w{ category }){|uri,localname,qname,attributes| 
         | 
| 25 | 
            +
                  category = Category.new
         | 
| 26 | 
            +
                  category.topic = currentTopic if(currentTopic)
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                @parser.listen(['topicstar','thatstar','star']){|u,localname,qn,attributes|
         | 
| 30 | 
            +
                  openLabels[-1].add(Star.new(localname,attributes))
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ### condition -- random
         | 
| 34 | 
            +
                @parser.listen(%w{ condition }){|uri,localname,qname,attributes|
         | 
| 35 | 
            +
                  if(attributes.key?('value'))
         | 
| 36 | 
            +
                    currentCondition = Condition.new(attributes)
         | 
| 37 | 
            +
                  else
         | 
| 38 | 
            +
                    currentCondition = ListCondition.new(attributes)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                  openLabels[-1].add(currentCondition)
         | 
| 41 | 
            +
                  openLabels.push(currentCondition)
         | 
| 42 | 
            +
                }
         | 
| 43 | 
            +
                
         | 
| 44 | 
            +
                @parser.listen(%w{ random }){|uri,localname,qname,attributes|
         | 
| 45 | 
            +
                  currentCondition = Random.new
         | 
| 46 | 
            +
                  openLabels[-1].add(currentCondition)
         | 
| 47 | 
            +
                  openLabels.push(currentCondition)
         | 
| 48 | 
            +
                }
         | 
| 49 | 
            +
                
         | 
| 50 | 
            +
                @parser.listen(:characters, %w{ condition }){|text|
         | 
| 51 | 
            +
                  next if(text =~ /^\s+$/)
         | 
| 52 | 
            +
                  currentCondition.add(text)
         | 
| 53 | 
            +
                }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                @parser.listen(%w{ li }){|uri,localname,qname,attributes|
         | 
| 56 | 
            +
                  next unless currentCondition
         | 
| 57 | 
            +
                  currentCondition.setListElement(attributes)
         | 
| 58 | 
            +
                }
         | 
| 59 | 
            +
                
         | 
| 60 | 
            +
                @parser.listen(:characters,%w{ li }){|text|
         | 
| 61 | 
            +
                  next unless currentCondition
         | 
| 62 | 
            +
                  currentCondition.add(text)
         | 
| 63 | 
            +
                }
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                @parser.listen(:end_element, ['condition','random']){
         | 
| 66 | 
            +
                  currentCondition = nil
         | 
| 67 | 
            +
                  openLabels.pop      
         | 
| 68 | 
            +
                }
         | 
| 69 | 
            +
            ### end condition -- random
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                @parser.listen([/^get.*/,/^bot_*/,'for_fun',/that$/, 'question']){
         | 
| 72 | 
            +
                               |uri,localname,qname,attributes|
         | 
| 73 | 
            +
                  unless(openLabels.empty?)
         | 
| 74 | 
            +
                    openLabels[-1].add(ReadOnlyTag.new(localname, attributes))
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                }
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                @parser.listen(['bot','name']){|uri,localname,qname,attributes|
         | 
| 79 | 
            +
                  if(localname == 'bot')
         | 
| 80 | 
            +
                    localname = 'bot_'+attributes['name']
         | 
| 81 | 
            +
                  else
         | 
| 82 | 
            +
                    localname = 'bot_name'
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                  if(patternIsOpen)
         | 
| 85 | 
            +
                    category.add_pattern(ReadOnlyTag.new(localname, {}))
         | 
| 86 | 
            +
                  elsif(thatIsOpen)
         | 
| 87 | 
            +
                    category.add_that(ReadOnlyTag.new(localname, {}))
         | 
| 88 | 
            +
                  else
         | 
| 89 | 
            +
                    openLabels[-1].add(ReadOnlyTag.new(localname, {}))
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                }
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            ### set
         | 
| 94 | 
            +
                @parser.listen([/^set_*/,'set']){|uri,localname,qname,attributes|
         | 
| 95 | 
            +
                  setObj = SetTag.new(localname,attributes)    
         | 
| 96 | 
            +
                  openLabels[-1].add(setObj)
         | 
| 97 | 
            +
                  openLabels.push(setObj)
         | 
| 98 | 
            +
                }
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                @parser.listen(:characters,[/^set_*/]){|text|
         | 
| 101 | 
            +
                  openLabels[-1].add(text)    
         | 
| 102 | 
            +
                }
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                @parser.listen(:end_element, [/^set_*/,'set']){
         | 
| 105 | 
            +
                  openLabels.pop      
         | 
| 106 | 
            +
                }
         | 
| 107 | 
            +
            ### end set
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            ### pattern
         | 
| 110 | 
            +
                @parser.listen(%w{ pattern }){patternIsOpen = true}
         | 
| 111 | 
            +
                @parser.listen(:characters,%w{ pattern }){|text| 
         | 
| 112 | 
            +
                  #TODO verify if case insensitive. Cross check with facade
         | 
| 113 | 
            +
                  category.add_pattern(text.upcase)
         | 
| 114 | 
            +
                }
         | 
| 115 | 
            +
                @parser.listen(:end_element, %w{ pattern }){patternIsOpen = false}
         | 
| 116 | 
            +
            #end pattern
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            #### that
         | 
| 119 | 
            +
                @parser.listen(%w{ that }){thatIsOpen = true}
         | 
| 120 | 
            +
                @parser.listen(:characters,%w{ that }){|text| category.add_that(text)}
         | 
| 121 | 
            +
                @parser.listen(:end_element, %w{ that }){thatIsOpen = false}
         | 
| 122 | 
            +
            ### end that
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            ### template
         | 
| 125 | 
            +
                @parser.listen(%w{ template }){ 
         | 
| 126 | 
            +
                  category.template = Template.new 
         | 
| 127 | 
            +
                  openLabels.push(category.template)
         | 
| 128 | 
            +
                }
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                @parser.listen(:characters, %w{ template }){|text|
         | 
| 131 | 
            +
                  category.template.append(text)
         | 
| 132 | 
            +
                }
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                @parser.listen(:end_element, %w{ template }){
         | 
| 135 | 
            +
                  openLabels.pop
         | 
| 136 | 
            +
                }
         | 
| 137 | 
            +
            ### end template
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                @parser.listen(%w{ input }){|uri,localname,qname,attributes|
         | 
| 140 | 
            +
                  category.template.add(Input.new(attributes))
         | 
| 141 | 
            +
                }
         | 
| 142 | 
            +
             | 
| 143 | 
            +
            ### think
         | 
| 144 | 
            +
                @parser.listen(:start_element, %w{ think }){
         | 
| 145 | 
            +
                  openLabels[-1].add(Think.new('start'))
         | 
| 146 | 
            +
                }
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                @parser.listen(:end_element, %w{ think }){
         | 
| 149 | 
            +
                openLabels[-1].add(Think.new('end'))
         | 
| 150 | 
            +
                }
         | 
| 151 | 
            +
            ###end think
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                @parser.listen(:characters, %w{ uppercase }){|text|
         | 
| 154 | 
            +
                  openLabels[-1].add(text.upcase.gsub(/\s+/, ' '))
         | 
| 155 | 
            +
                }
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                @parser.listen(:characters, %w{ lowercase }){|text|
         | 
| 158 | 
            +
                  openLabels[-1].add(text.downcase.gsub(/\s+/, ' '))
         | 
| 159 | 
            +
                }
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                @parser.listen(:characters, %w{ formal }){|text|
         | 
| 162 | 
            +
                  text.gsub!(/(\w+)/){$1.capitalize}
         | 
| 163 | 
            +
                  openLabels[-1].add(text.gsub(/\s+/, ' '))
         | 
| 164 | 
            +
                }
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                @parser.listen(:characters, %w{ sentence }){|text|
         | 
| 167 | 
            +
                  openLabels[-1].add(text.capitalize.gsub(/\s+/, ' '))
         | 
| 168 | 
            +
                }
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                @parser.listen(%w{ date }){
         | 
| 171 | 
            +
                  openLabels[-1].add(Sys_Date.new)
         | 
| 172 | 
            +
                }
         | 
| 173 | 
            +
                
         | 
| 174 | 
            +
                @parser.listen(:characters, %w{ system }){|text|
         | 
| 175 | 
            +
                  openLabels[-1].add(Command.new(text))
         | 
| 176 | 
            +
                }
         | 
| 177 | 
            +
                
         | 
| 178 | 
            +
                @parser.listen(%w{ size }){ 
         | 
| 179 | 
            +
                  openLabels[-1].add(Size.new)
         | 
| 180 | 
            +
                }
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                @parser.listen(%w{ sr }){|uri,localname,qname,attributes|
         | 
| 183 | 
            +
                  openLabels[-1].add(Srai.new(Star.new('star',{})))
         | 
| 184 | 
            +
                }
         | 
| 185 | 
            +
            ### srai    
         | 
| 186 | 
            +
                @parser.listen(%w{ srai }){|uri,localname,qname,attributes|
         | 
| 187 | 
            +
                  currentSrai = Srai.new
         | 
| 188 | 
            +
                  openLabels[-1].add(currentSrai)
         | 
| 189 | 
            +
                  openLabels.push(currentSrai)
         | 
| 190 | 
            +
                }
         | 
| 191 | 
            +
                
         | 
| 192 | 
            +
                @parser.listen(:characters, %w{ srai }){|text|
         | 
| 193 | 
            +
                  currentSrai = Srai.new
         | 
| 194 | 
            +
                  currentSrai.add(text)
         | 
| 195 | 
            +
                }
         | 
| 196 | 
            +
                
         | 
| 197 | 
            +
                @parser.listen(:end_element, %w{ srai }){
         | 
| 198 | 
            +
                  currentSrai = nil
         | 
| 199 | 
            +
                  openLabels.pop
         | 
| 200 | 
            +
                }
         | 
| 201 | 
            +
            ### end srai
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            ### gender
         | 
| 204 | 
            +
                @parser.listen(%w{ gender }){|uri,localname,qname,attributes|
         | 
| 205 | 
            +
                  currentGender = Gender.new
         | 
| 206 | 
            +
                  openLabels[-1].add(currentGender)
         | 
| 207 | 
            +
                  openLabels.push(currentGender)
         | 
| 208 | 
            +
                }
         | 
| 209 | 
            +
                
         | 
| 210 | 
            +
                @parser.listen(:characters, %w{ gender }){|text|
         | 
| 211 | 
            +
                  currentGender.add(text)
         | 
| 212 | 
            +
                }
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                @parser.listen(:end_element, %w{ gender }){
         | 
| 215 | 
            +
                  currentGender = nil
         | 
| 216 | 
            +
                  openLabels.pop
         | 
| 217 | 
            +
                }
         | 
| 218 | 
            +
            ### end gender
         | 
| 219 | 
            +
             | 
| 220 | 
            +
            ### person
         | 
| 221 | 
            +
                @parser.listen(%w{ person }){|uri,localname,qname,attributes|
         | 
| 222 | 
            +
                  currentPerson = Person.new
         | 
| 223 | 
            +
                  openLabels[-1].add(currentPerson)
         | 
| 224 | 
            +
                  openLabels.push(currentPerson)
         | 
| 225 | 
            +
                }
         | 
| 226 | 
            +
                
         | 
| 227 | 
            +
                @parser.listen(:characters, %w{ person }){|text|
         | 
| 228 | 
            +
                  currentPerson.add(text)
         | 
| 229 | 
            +
                }
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                @parser.listen(:end_element, %w{ person }){
         | 
| 232 | 
            +
                  currentPerson = nil
         | 
| 233 | 
            +
                  openLabels.pop
         | 
| 234 | 
            +
                }
         | 
| 235 | 
            +
            ### end person
         | 
| 236 | 
            +
             | 
| 237 | 
            +
            ### person2
         | 
| 238 | 
            +
                @parser.listen(%w{ person2 }){|uri,localname,qname,attributes|
         | 
| 239 | 
            +
                  currentPerson2 = Person2.new
         | 
| 240 | 
            +
                  openLabels[-1].add(currentPerson2)
         | 
| 241 | 
            +
                  openLabels.push(currentPerson2)
         | 
| 242 | 
            +
                }
         | 
| 243 | 
            +
                
         | 
| 244 | 
            +
                @parser.listen(:characters, %w{ person2 }){|text|
         | 
| 245 | 
            +
                  currentPerson2.add(text)
         | 
| 246 | 
            +
                }
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                @parser.listen(:end_element, %w{ person2 }){
         | 
| 249 | 
            +
                  currentPerson2 = nil
         | 
| 250 | 
            +
                  openLabels.pop
         | 
| 251 | 
            +
                }
         | 
| 252 | 
            +
            ### end perso2
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                @parser.listen(:end_element, %w{ category }){ @learner.learn(category) }
         | 
| 255 | 
            +
             | 
| 256 | 
            +
            ### topic
         | 
| 257 | 
            +
                @parser.listen(%w{ topic }){|uri,localname,qname,attributes|
         | 
| 258 | 
            +
                  currentTopic = attributes['name']
         | 
| 259 | 
            +
                }
         | 
| 260 | 
            +
                
         | 
| 261 | 
            +
                @parser.listen(:end_element, %w{ topic }){
         | 
| 262 | 
            +
                  currentTopic = nil
         | 
| 263 | 
            +
                }
         | 
| 264 | 
            +
            ### end topic
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                @parser.parse
         | 
| 267 | 
            +
              end
         | 
| 268 | 
            +
            end #Aiml@parser
         | 
| 269 | 
            +
            end
         | 
| @@ -0,0 +1,75 @@ | |
| 1 | 
            +
            require 'yaml'
         | 
| 2 | 
            +
            require 'programr/history'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module ProgramR
         | 
| 5 | 
            +
            class Environment
         | 
| 6 | 
            +
              @@readOnlyTags = nil
         | 
| 7 | 
            +
              @@history      = nil
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def initialize
         | 
| 10 | 
            +
                return self unless(@@readOnlyTags == nil)
         | 
| 11 | 
            +
                @@readOnlyTags = YAML::load(
         | 
| 12 | 
            +
                                      File.open( 
         | 
| 13 | 
            +
                                        File.dirname(__FILE__) +
         | 
| 14 | 
            +
                                          "/../../conf/readOnlyTags.yaml"))
         | 
| 15 | 
            +
                @@history      = History.new
         | 
| 16 | 
            +
                srand(1)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              def get(aTag)
         | 
| 20 | 
            +
                send(aTag)
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def set(aTag,aValue)
         | 
| 24 | 
            +
                @@history.updateTopic(aValue) if(aTag == 'topic')
         | 
| 25 | 
            +
                @@readOnlyTags[aTag] = aValue
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def method_missing(methId)
         | 
| 29 | 
            +
                tag = methId.id2name
         | 
| 30 | 
            +
                return @@history.send(tag) if(tag =~ /that$/)
         | 
| 31 | 
            +
                return @@readOnlyTags[tag] if(@@readOnlyTags.key?(tag))
         | 
| 32 | 
            +
                ''
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
              
         | 
| 35 | 
            +
              def test
         | 
| 36 | 
            +
                #should overwrite test ....
         | 
| 37 | 
            +
                return @@readOnlyTags[tag] if(@@readOnlyTags.key?(tag))
         | 
| 38 | 
            +
                ''
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              def star(anIndex)
         | 
| 42 | 
            +
                @@history.getStar(anIndex)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
              
         | 
| 45 | 
            +
              def thatstar(anIndex)
         | 
| 46 | 
            +
                @@history.getThatStar(anIndex)
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
              
         | 
| 49 | 
            +
              def topicstar(anIndex)
         | 
| 50 | 
            +
                @@history.getTopicStar(anIndex)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
              
         | 
| 53 | 
            +
              def male
         | 
| 54 | 
            +
                @@readOnlyTags['gender'] = 'male'
         | 
| 55 | 
            +
                return 'male'
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
              
         | 
| 58 | 
            +
              def female
         | 
| 59 | 
            +
                @@readOnlyTags['gender'] = 'female'
         | 
| 60 | 
            +
                return 'female'
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
              
         | 
| 63 | 
            +
              def question
         | 
| 64 | 
            +
                @@readOnlyTags['question'][rand(@@readOnlyTags['question'].length-1)]
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def getRandom(anArrayofChoices)
         | 
| 68 | 
            +
                anArrayofChoices[rand(anArrayofChoices.length-1)]
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def getStimula(anIndex)
         | 
| 72 | 
            +
                @@history.getStimula(anIndex)
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| 75 | 
            +
            end
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            require 'programr/graph_master'
         | 
| 2 | 
            +
            require 'programr/aiml_parser'
         | 
| 3 | 
            +
            require 'programr/history'
         | 
| 4 | 
            +
            require 'programr/utils'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module ProgramR
         | 
| 7 | 
            +
            class Facade
         | 
| 8 | 
            +
              def initialize(cache = nil)
         | 
| 9 | 
            +
                @graph_master = GraphMaster.new
         | 
| 10 | 
            +
                @parser       = AimlParser.new(@graph_master)
         | 
| 11 | 
            +
                @history      = History.new
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def learn(files)
         | 
| 15 | 
            +
                AimlFinder::find(files).each{|f| File.open(f,'r'){|f| @parser.parse f} }
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def loading(theCacheFilename='cache')
         | 
| 19 | 
            +
                cache = Cache::loading(theCacheFilename)
         | 
| 20 | 
            +
                @graph_master = cache if cache
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def merging(theCacheFilename='cache')
         | 
| 24 | 
            +
                cache = Cache::loading(theCacheFilename)
         | 
| 25 | 
            +
                @graph_master.merge(cache) if cache
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def dumping(theCacheFilename='cache')
         | 
| 29 | 
            +
                Cache::dumping(theCacheFilename,@graph_master)
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
              
         | 
| 32 | 
            +
              def get_reaction(stimula,firstStimula=true)
         | 
| 33 | 
            +
                starGreedy = []  
         | 
| 34 | 
            +
            #TODO verify if case insensitive. Cross check with parser
         | 
| 35 | 
            +
                #@history.updateStimula(stimula.upcase) if(firstStimula)
         | 
| 36 | 
            +
            @history.updateStimula(stimula.upcase) if(firstStimula)
         | 
| 37 | 
            +
                thinkIsActive = false
         | 
| 38 | 
            +
            reaction = @graph_master.get_reaction(stimula.upcase, @history.that,
         | 
| 39 | 
            +
                                                      @history.topic,starGreedy)
         | 
| 40 | 
            +
                @history.updateStarMatches(starGreedy)
         | 
| 41 | 
            +
                res = ''
         | 
| 42 | 
            +
                reaction.each{|tocken| 
         | 
| 43 | 
            +
                  if(tocken.class == Srai)
         | 
| 44 | 
            +
                    tocken = get_reaction(tocken.pattern,false)
         | 
| 45 | 
            +
                    @history.updateStarMatches(starGreedy)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  if tocken.class == Think
         | 
| 48 | 
            +
                    thinkIsActive = ! thinkIsActive
         | 
| 49 | 
            +
                    next
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  value = tocken.to_s
         | 
| 52 | 
            +
                  res += value unless(thinkIsActive)
         | 
| 53 | 
            +
                }
         | 
| 54 | 
            +
                #TODO verify if case insensitive. Cross check with main program & parser
         | 
| 55 | 
            +
                @history.updateResponse(res.strip.upcase) if(firstStimula)
         | 
| 56 | 
            +
                return res.strip
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def to_s
         | 
| 60 | 
            +
                @graph_master.to_s
         | 
| 61 | 
            +
              end  
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              #  def getBotName()end
         | 
| 64 | 
            +
            end
         | 
| 65 | 
            +
            end
         | 
| @@ -0,0 +1,110 @@ | |
| 1 | 
            +
            require 'programr/aiml_elements'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ProgramR
         | 
| 4 | 
            +
            THAT  = '<that>'
         | 
| 5 | 
            +
            TOPIC = '<topic>'
         | 
| 6 | 
            +
            class GraphMaster
         | 
| 7 | 
            +
              attr_reader :graph
         | 
| 8 | 
            +
              def initialize
         | 
| 9 | 
            +
                @graph = Node.new
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def merge(aCache)
         | 
| 13 | 
            +
                @graph.merge(aCache.graph)
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
              
         | 
| 16 | 
            +
              def learn(category)
         | 
| 17 | 
            +
                path = category.get_pattern
         | 
| 18 | 
            +
                path += [THAT] + category.get_that unless (category.get_that).empty?
         | 
| 19 | 
            +
                path += [TOPIC] + category.topic.split(/\s+/) if category.topic
         | 
| 20 | 
            +
                @graph.learn(category, path)
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def to_s
         | 
| 24 | 
            +
                @graph.inspectNode()
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def get_reaction(stimula, last_said,cur_topic,starGreedy)
         | 
| 28 | 
            +
                path = "#{stimula} #{THAT} #{last_said} #{TOPIC} #{cur_topic}"
         | 
| 29 | 
            +
                template = @graph.get_template(path.split(/\s+/),starGreedy)
         | 
| 30 | 
            +
                return template.value unless(template == nil)
         | 
| 31 | 
            +
                return []
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            class Node
         | 
| 36 | 
            +
              attr_reader :children
         | 
| 37 | 
            +
              def initialize
         | 
| 38 | 
            +
                @template = nil
         | 
| 39 | 
            +
                @children = {}
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              def merge(aCache)
         | 
| 43 | 
            +
                aCache.children.keys.each do |key|
         | 
| 44 | 
            +
                  if(@children.key?(key))
         | 
| 45 | 
            +
                    @children[key].merge(aCache.children[key])
         | 
| 46 | 
            +
            	next
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                  @children[key] = aCache.children[key]
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
              
         | 
| 52 | 
            +
              def learn(category, path)
         | 
| 53 | 
            +
                branch = path.shift
         | 
| 54 | 
            +
                return @template = category.template unless branch
         | 
| 55 | 
            +
                @children[branch] = Node.new unless @children[branch]
         | 
| 56 | 
            +
                @children[branch].learn(category, path)
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def get_template(pattern,starGreedy,isGreedy=false)  
         | 
| 60 | 
            +
                currentTemplate = nil
         | 
| 61 | 
            +
                gotValue        = nil
         | 
| 62 | 
            +
                curGreedy       = []
         | 
| 63 | 
            +
                if(@template)
         | 
| 64 | 
            +
                  if(isGreedy)
         | 
| 65 | 
            +
            	starGreedy.push(pattern.shift) until(pattern.empty?||pattern[0]==THAT ||
         | 
| 66 | 
            +
            	                                     pattern[0] == TOPIC)
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                  return @template if(pattern.empty?)
         | 
| 69 | 
            +
                  currentTemplate = @template if(pattern[0] == THAT || pattern[0] == TOPIC)
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
                branch = pattern.shift
         | 
| 72 | 
            +
                isGreedy = false if(branch == THAT || branch == TOPIC)
         | 
| 73 | 
            +
                unless(branch != THAT || @children.key?(THAT))
         | 
| 74 | 
            +
                  branch = pattern.shift until (branch == nil or branch == TOPIC)
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
                return nil unless(branch)
         | 
| 77 | 
            +
                if(@children[branch])
         | 
| 78 | 
            +
                  gotValue = @children[branch].get_template(pattern.clone,curGreedy)
         | 
| 79 | 
            +
                elsif(isGreedy)
         | 
| 80 | 
            +
                  curGreedy.push(branch)
         | 
| 81 | 
            +
                  gotValue = get_template(pattern.clone,curGreedy,true)
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
                if(gotValue)
         | 
| 84 | 
            +
                  starGreedy.push(branch) if(branch == THAT || branch == TOPIC)
         | 
| 85 | 
            +
                  starGreedy.concat(curGreedy)
         | 
| 86 | 
            +
                  return gotValue
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
                return currentTemplate if currentTemplate   
         | 
| 89 | 
            +
                ["_","*"].each do |star|
         | 
| 90 | 
            +
                  next unless(@children.key?(star))
         | 
| 91 | 
            +
                  next unless(gotValue=@children[star].get_template(pattern.clone,
         | 
| 92 | 
            +
                                                                    curGreedy,true))
         | 
| 93 | 
            +
            starGreedy.push(branch) if(branch == THAT || branch == TOPIC)
         | 
| 94 | 
            +
                  starGreedy.concat(['<newMatch>',branch].concat(curGreedy))
         | 
| 95 | 
            +
                  return gotValue 
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
                return nil
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              def inspectNode(nodeId = nil, ind = 0)
         | 
| 101 | 
            +
                str = ''
         | 
| 102 | 
            +
                str += '| '*(ind - 1) + "|_#{nodeId}" unless ind == 0
         | 
| 103 | 
            +
                str += ": [#{@template.inspect}]" if @template
         | 
| 104 | 
            +
                str += "\n" unless ind == 0
         | 
| 105 | 
            +
                @children.each_key{|c| str += @children[c].inspectNode(c, ind+1)}
         | 
| 106 | 
            +
                str
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
            end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            end #ProgramR
         |