public static function srai($in_input) { //print 'SRAI '.$in_input. '<br>'; /* check recursion level */ JxBotConverse::$srai_level++; if (JxBotConverse::$srai_level > JxBotConverse::MAX_SRAI_RECURSION) { throw new Exception('Too much recursion (in SRAI)'); } /* process each sentence separately */ $sentences = JxBotNL::split_sentences($in_input); $output = array(); foreach ($sentences as $sentence) { $output[] = JxBotConverse::sentence_respond($sentence); } $output = implode(' ', $output); JxBotConverse::$srai_level--; return $output; }
public static function set_values($in_set_name) { $stmt = JxBotDB::$db->prepare(' SELECT phrase FROM set_item JOIN _set ON set_item.id=_set.id WHERE _set.name=? ORDER BY phrase'); $stmt->execute(array(trim($in_set_name))); $values = array(); $rows = $stmt->fetchAll(PDO::FETCH_NUM); foreach ($rows as $row) { $values[] = JxBotNL::normalise($row[0]); } return $values; }
public static function normalise_pattern($in_pattern) { $output = $in_pattern; $output = JxBotNL::upper($output); $output = JxBotNL::strip_accents($output); /* TODO: Ought to consider stripping only selected punctuation here. */ $output = JxBotNL::split_words($output); return $output; }
public function generate($in_context) { switch ($this->name) { case 'system': /* security implications; will not implement until reasonable controls are developed and an on/off switch */ /* security implications; will not implement until reasonable controls are developed and an on/off switch */ case 'javascript': /* server-side javascript is not implemented */ break; case 'think': $this->text_value($in_context); break; case 'template': case 'gossip': /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ case 'x-learn-1': /* AIML 1 learn tag to be filtered on import and contents passed through without further action */ return $this->text_value($in_context); case 'random': $count = $this->child_element_count(); $index = mt_rand(1, $count) - 1; return $this->child_element($index)->text_value($in_context); case 'condition': $loop = false; // preparation for AIML 2 loop; will need to keep a stack & check the stack so it can be toggled // by a <loop/> element anywhere in the depth of the <li> do { $count = $this->child_element_count('li'); if ($count == 0) { $predicate = $this->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $this->child_or_attr_named($in_context, 'value'); if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $this->text_value($in_context, array('name', 'value')); } } else { $count = $this->child_element_count(); $predicate = $this->child_or_attr_named($in_context, 'name', null); if ($predicate !== null) { $value = JxBotConverse::predicate($predicate); for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value')); } } } else { for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $predicate = $item->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value', 'name')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value', 'name')); } } } } } while ($loop); break; case 'star': case 'thatstar': case 'topicstar': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return $this->get_capture($in_context, $this->name, $index); case 'srai': return JxBotConverse::srai($this->text_value($in_context)); case 'sr': /* srai star /srai */ return JxBotConverse::srai($this->get_capture($in_context, 'star', 1)); case 'bot': case 'get': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name !== '') { if ($this->name == 'get') { return JxBotConverse::predicate($name); } else { if ($name == 'size') { return JxBotNLData::pattern_count(); } else { if ($name == 'age') { return JxBotElement::compute_age(); } else { if ($name == 'birthday') { return JxBotElement::birthday(); } else { return JxBotConfig::predicate($name); } } } } } break; case 'tag': /* non-standard Tag feature */ $name = trim($this->child_or_attr_named($in_context, 'name')); return $in_context->tag_value($name); case 'id': return JxBotConverse::predicate('id'); case 'size': /* we return the number of patterns, which is equivalent to AIML standard category count; since in JxBot one category != one pattern. */ return JxBotNLData::pattern_count(); case 'vocabulary': return JxBotNLData::word_count(); case 'version': return JxBot::VERSION; case 'program': return JxBot::PROGRAM . ' ' . JxBot::VERSION; case 'set': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name != '') { $value = $this->text_value($in_context, array('name')); JxBotConverse::set_predicate($name, $value); return $value; } break; case 'date': $php_format = 'r'; /* default - AIML 1.0 - we specify date & time format */ return date($php_format); case 'uppercase': return JxBotNL::upper($this->text_value($in_context)); case 'lowercase': return JxBotNL::lower($this->text_value($in_context)); case 'formal': return JxBotNL::formal($this->text_value($in_context)); case 'sentence': return JxBotNL::sentence($this->text_value($in_context)); case 'explode': return JxBotNL::explode($this->text_value($in_context)); case 'normalize': return JxBotNL::template_normalize($this->text_value($in_context)); case 'denormalize': return JxBotNL::template_denormalize($this->text_value($in_context)); case 'gender': if (count($this->children) == 0) { return JxBotNL::remap('gender', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('gender', $this->text_value($in_context)); case 'person': if (count($this->children) == 0) { return JxBotNL::remap('person', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person', $this->text_value($in_context)); case 'person2': if (count($this->children) == 0) { return JxBotNL::remap('person2', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person2', $this->text_value($in_context)); case 'map': $map_name = $this->child_or_attr_named($in_context, 'name'); return JxBotNL::remap($map_name, $this->text_value($in_context, array('name'))); case 'that': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_response = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $response = JxBotConverse::history_response($in_response - 1); $sentences = JxBotNL::split_sentences($response); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'input': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_request = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $request = JxBotConverse::history_request($in_request - 1); $sentences = JxBotNL::split_sentences($request); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'request': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_request($index - 1); case 'response': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_response($index - 1); default: /* push unknown content & tags through to output */ // ! REVIEW: A better policy might be to tightly control which tags are // allowed through, or provide an appropriate system option. return $this->flatten(); } }
public static function match($in_input, $in_that, $in_topic) { if ($in_that === null) { $in_that = ''; } if ($in_topic === null) { $in_topic = ''; } $context = new JxBotEngine(); $context->tags = JxBotEngine::compute_tags($in_input); //var_dump($context->tags); $search_terms = JxBotNL::normalise($in_input); $search_terms[] = ':'; $terms = JxBotNL::normalise($in_that); if (count($terms) == 0) { $search_terms[] = '*'; } else { $search_terms = array_merge($search_terms, $terms); } $search_terms[] = ':'; $terms = JxBotNL::normalise($in_topic); if (count($terms) == 0) { $search_terms[] = '*'; } else { $search_terms = array_merge($search_terms, $terms); } /*print 'Search: <pre>'; var_dump($search_terms); print '</pre>';*/ $context->input_terms = $search_terms; $context->term_index = 0; $context->term_limit = count($search_terms); $context->wild_values = array(); $context->wild_that_values = array(); $context->wild_topic_values = array(); $context->unwind_stage = 2; $context->search_depth = 0; //var_dump($search_terms); //print '<br>'; $matched_pattern = $context->walk(0, 0); if ($matched_pattern === false) { return false; } //print 'Matched pattern: '.$matched_pattern.' ('.$context->search_depth.')<br>'; $stmt = JxBotDB::$db->prepare('SELECT category,term_count FROM pattern WHERE id=?'); $stmt->execute(array($matched_pattern)); $category = $stmt->fetchAll(PDO::FETCH_NUM); $context->matched_category_id = $category[0][0]; $context->term_count = $category[0][1]; return $context; }