use std::path::PathBuf;
use crate::{sonicobject::{SonicObject, SonicPersistObject}, sonicobject};
use regex::Regex;
use sonic_serde_object::SonicSerdeObject;
#[derive(Clone)]
pub struct PatternMgr {
dict_underscore: u8,
dict_star: u8,
dict_template: u8,
dict_that: u8,
dict_topic: u8,
dict_bot_name: u8,
pub root: SonicObject,
template_count: u128,
bot_name: String,
punc_strip_re: Regex,
whitespace_re: Regex,
}
#[allow(unused_mut, unused_assignments)]
impl PatternMgr {
pub fn new() -> Self {
let mut dict_underscore = 0;
let mut dict_star = 1;
let mut dict_template = 2;
let mut dict_that = 3;
let mut dict_topic = 4;
let mut dict_bot_name = 5;
let mut template_count = 0;
let mut root = SonicObject::new(SonicSerdeObject::new_map());
let mut bot_name = "Nameless".to_string();
let mut a = "[".to_string();
let punctuation = regex::escape(r#"`~!@#$%^&*()-_=+[{]}\|;:'",<.>/?"#);
a.push_str(punctuation.as_str());
a.push_str("]");
let mut punc_strip_re = Regex::new(a.as_str()).unwrap();
let mut whitespace_re = Regex::new(r#"\s+"#).unwrap();
Self {
dict_underscore: dict_underscore,
dict_star: dict_star,
dict_template: dict_template,
dict_that: dict_that,
dict_topic: dict_topic,
dict_bot_name: dict_bot_name,
root: root,
template_count: template_count,
bot_name: bot_name,
punc_strip_re: punc_strip_re,
whitespace_re: whitespace_re,
}
}
pub fn num_templates(&mut self) -> u128 {
self.template_count
}
pub fn set_bot_name(&mut self, name: impl Into<String>) -> () {
self.bot_name = name.into().split_whitespace().collect::<Vec<&str>>().join(" ");
}
pub fn dump(&mut self) -> () {
println!("{:?}", self.root);
}
pub fn save(&mut self, filename: PathBuf) {
println!("{}", self.root.keys().len());
let mut out_file = SonicPersistObject::new(filename);
out_file.insert("templatecount", self.template_count.to_string());
out_file.insert("botname", self.bot_name.clone());
out_file.insert("root", self.root.clone().value);
out_file.flush();
drop(out_file);
}
pub fn restore(&mut self, filename: PathBuf) {
let mut in_file = SonicPersistObject::new(filename);
self.template_count = in_file.get("templatecount").value.as_str().unwrap().parse::<u128>().unwrap();
self.bot_name = in_file.get("botname").value.as_str().unwrap().to_string();
self.root = in_file.get("root");
println!("{}", self.root.keys().len());
}
fn recursive_add(&self, key_value_vec: Vec<(SonicSerdeObject, SonicSerdeObject)>, root: SonicObject, depth: usize) -> SonicObject {
let mut new_key_val = key_value_vec.clone();
let mut new_root = root;
if key_value_vec.len() == 1 {
new_root.insert(key_value_vec[0].0.clone(), key_value_vec[0].1.clone());
return new_root;
}
new_key_val.remove(0);
if !new_root.contains(key_value_vec[0].0.clone()) {
new_root.insert(key_value_vec[0].0.clone(), SonicSerdeObject::new_map());
}
let val = self.recursive_add(new_key_val, new_root.get(key_value_vec[0].0.clone()).unwrap(), depth + 1);
new_root.insert(key_value_vec[0].0.clone(), val.value);
return new_root
}
pub fn add(&mut self, data: (String, String, String), template: SonicObject) -> () {
let (pattern, that, topic) = data.clone();
let mut node = self.root.clone();
if pattern.as_str() == "A LOT OF *" {
}
let mut key_value_vec: Vec<(SonicSerdeObject, SonicSerdeObject)> = Vec::new();
let mut key = SonicSerdeObject::U8(255);
for word in pattern.split_whitespace() {
key = SonicSerdeObject::String(word.to_string());
if word == "_" {
key = SonicSerdeObject::U8(self.dict_underscore);
} else if word == "*" {
key = SonicSerdeObject::U8(self.dict_star);
} else if word == "BOT_NAME" {
key = SonicSerdeObject::U8(self.dict_bot_name);
}
if !node.contains(key.clone()) {
node.insert(key.clone(), SonicSerdeObject::new_map());
} key_value_vec.push((key.clone(), node.getvalue(key.clone()).unwrap()));
node = node.get(key.clone()).unwrap();
}
if that.len() > 0 {
if !node.contains(SonicSerdeObject::U8(self.dict_that)) {
node.insert(SonicSerdeObject::U8(self.dict_that), SonicSerdeObject::new_map());
}
key_value_vec.push((SonicSerdeObject::U8(self.dict_that), node.getvalue(SonicSerdeObject::U8(self.dict_that)).unwrap()));
node = node.get(SonicSerdeObject::U8(self.dict_that)).unwrap();
for word in that.split_whitespace() {
key = SonicSerdeObject::String(word.to_string());
if word == "_" {
key = SonicSerdeObject::U8(self.dict_underscore);
} else if word == "*" {
key = SonicSerdeObject::U8(self.dict_star);
}
if !node.contains(key.clone()) {
node.insert(key.clone(), SonicSerdeObject::new_map());
} key_value_vec.push((key.clone(), node.getvalue(key.clone()).unwrap()));
node = node.get(key.clone()).unwrap();
}
}
if topic.len() > 0 {
if !node.contains(SonicSerdeObject::U8(self.dict_topic)) {
node.insert(SonicSerdeObject::U8(self.dict_topic), SonicSerdeObject::new_map());
}
key_value_vec.push((SonicSerdeObject::U8(self.dict_topic), node.getvalue(SonicSerdeObject::U8(self.dict_topic)).unwrap()));
node = node.get(SonicSerdeObject::U8(self.dict_topic)).unwrap();
for word in topic.split_whitespace() {
key = SonicSerdeObject::String(word.to_string());
if word == "_" {
key = SonicSerdeObject::U8(self.dict_underscore);
} else if word == "*" {
key = SonicSerdeObject::U8(self.dict_star);
}
if !node.contains(key.clone()) {
node.insert(key.clone(), SonicSerdeObject::new_map());
} key_value_vec.push((key.clone(), node.getvalue(key.clone()).unwrap()));
node = node.get(key.clone()).unwrap();
}
}
if !node.contains(SonicSerdeObject::U8(self.dict_template)) {
self.template_count = self.template_count + 1;
}
node.insert(SonicSerdeObject::U8(self.dict_template), template.value.clone());
key_value_vec.push((SonicSerdeObject::U8(self.dict_template), template.value.clone()));
if !self.root.contains(key_value_vec[0].0.clone()) {
self.root.insert(key_value_vec[0].0.clone(), SonicSerdeObject::new_map());
}
self.root.insert(key_value_vec[0].0.clone(), self.recursive_add(key_value_vec.clone()[1..].to_vec(), self.root.get(key_value_vec[0].0.clone()).unwrap(), 0).value);
}
pub fn _match(&mut self, words: Vec<String>, that_words: Vec<String>, topic_words: Vec<String>, root: SonicObject) -> Result<(Option<SonicObject>, Option<SonicObject>), sonicobject::SonicObjectError> {
let mut pattern: Option<SonicObject>;
let mut template: Option<SonicObject>;
if words.len() == 0 {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = None;
if that_words.len() > 0 {
match root.get(SonicSerdeObject::U8(self.dict_that)) {
Ok(_z) => {
match self._match(that_words, Vec::new(), topic_words, root.get(SonicSerdeObject::U8(self.dict_that)).unwrap()) {
Ok((p, t)) => {
pattern = p;
template = t;
if pattern.is_some() {
let mut temppattern = SonicObject::new(SonicSerdeObject::new_vec());
temppattern.push(SonicSerdeObject::U8(self.dict_that));
for pat in pattern.unwrap().clone() {
temppattern.push(pat.clone().value);
}
pattern = Some(temppattern.clone());
}
},
Err(sonicobject::SonicObjectError::KeyError(_y)) => {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = None;
},
Err(e) => {
panic!("{}", e);
}
};
},
Err(sonicobject::SonicObjectError::KeyError(_e)) => {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = None;
},
Err(_e) => {
();
}
}
} else if topic_words.len() > 0 {
match root.get(SonicSerdeObject::U8(self.dict_topic)) {
Ok(_z) => {
match self._match(topic_words, Vec::new(), Vec::new(), root.get(SonicSerdeObject::U8(self.dict_topic)).unwrap()) {
Ok((p, t)) => {
pattern = p;
template = t;
if pattern.is_some() {
let mut temppattern = SonicObject::new(SonicSerdeObject::new_vec());
temppattern.push(SonicSerdeObject::U8(self.dict_topic));
for pat in pattern.unwrap().clone() {
temppattern.push(pat.clone().value);
}
pattern = Some(temppattern.clone());
}
},
Err(sonicobject::SonicObjectError::KeyError(_y)) => {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = None;
},
Err(e) => {
panic!("{}", e);
}
};
},
Err(sonicobject::SonicObjectError::KeyError(_e)) => {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = None;
},
Err(_e) => {
();
}
}
}
if template.is_none() {
pattern = Some(SonicObject::new(SonicSerdeObject::new_vec()));
template = match root.get(SonicSerdeObject::U8(self.dict_template)) {
Ok(x) => Some(x),
Err(sonicobject::SonicObjectError::KeyError(_x)) => {
None
},
Err(e) => panic!("{}", e),
}
}
return Ok((pattern, template));
}
let mut first: String = (&words[0]).to_string();
let mut suffix: Vec<String> = words[1..].to_vec();
if root.contains(SonicSerdeObject::U8(self.dict_underscore)) {
for j in 0..(suffix.len() + 1) {
let mut suf = suffix[j..].to_vec();
let z = self._match(suf, that_words.clone(), topic_words.clone(), root.clone().get(SonicSerdeObject::U8(self.dict_underscore)).unwrap()).unwrap();
pattern = z.0;
template = z.1;
if template.is_some() {
let mut newpattern = SonicObject::new(SonicSerdeObject::new_vec());
newpattern.push(SonicSerdeObject::U8(self.dict_underscore));
for pat in pattern.unwrap() {
newpattern.push(pat.value)
}
return Ok((Some(newpattern), template));
}
}
}
if root.contains(SonicSerdeObject::String(first.clone())) {
let z = self._match(suffix.clone(), that_words.clone(), topic_words.clone(), root.get(SonicSerdeObject::String(first.clone())).unwrap()).unwrap();
pattern = z.0;
template = z.1;
if template.is_some() {
let mut newpattern = SonicObject::new(SonicSerdeObject::new_vec());
newpattern.push(SonicSerdeObject::String(first.clone()));
for pat in pattern.unwrap() {
newpattern.push(pat.value)
}
return Ok((Some(newpattern), template));
}
}
if root.contains(SonicSerdeObject::U8(self.dict_bot_name)) && first == self.bot_name {
let z = self._match(suffix.clone(), that_words.clone(), topic_words.clone(), root.get(SonicSerdeObject::U8(self.dict_bot_name)).unwrap()).unwrap();
pattern = z.0; let template = z.1;
if template.is_some() {
let mut newpattern = SonicObject::new(SonicSerdeObject::new_vec());
newpattern.push(SonicSerdeObject::String(first.clone()));
for pat in pattern.unwrap() {
newpattern.push(pat.value)
}
return Ok((Some(newpattern), template));
}
}
if root.contains(SonicSerdeObject::U8(self.dict_star)) {
for j in 0..(suffix.len() + 1) {
let mut suf = suffix[j..].to_vec();
let z = self._match(suf, that_words.clone(), topic_words.clone(), root.clone().get(SonicSerdeObject::U8(self.dict_star)).unwrap()).unwrap();
pattern = z.0;
template = z.1;
if template.is_some() {
let mut newpattern = SonicObject::new(SonicSerdeObject::new_vec());
newpattern.push(SonicSerdeObject::U8(self.dict_star));
for pat in pattern.unwrap() {
newpattern.push(pat.value)
}
return Ok((Some(newpattern), template));
}
}
}
Ok((None, None))
}
pub fn r#match(&mut self, pattern: String, that: String, topic: String) -> Option<SonicObject> {
let pattern = pattern.clone();
let mut that = that.clone();
let mut topic = topic.clone();
if pattern.len() == 0 {
return None;
}
let mut input: String = pattern.to_uppercase();
input = self.punc_strip_re.replace_all(input.as_str(), " ").to_string();
if that.trim().to_string() == String::new() {
that = "ULTRABOGUSDUMMYTHAT".to_string();
}
let mut that_input: String = that.to_uppercase().to_string();
that_input = self.punc_strip_re.replace_all(that_input.as_str(), " ").to_string();
that_input = self.whitespace_re.replace_all(that_input.as_str(), " ").to_string();
if topic.trim().to_string() == String::new() {
topic = "ULTRABOGUSDUMMYTOPIC".to_string();
}
let mut topic_input: String = topic.to_uppercase().to_string();
topic_input = self.punc_strip_re.replace_all(topic_input.as_str(), " ").to_string();
let (_patmatch, template) = self._match(input.split_whitespace().map(|inword| inword.to_string()).collect(), that_input.split_whitespace().map(|inword| inword.to_string()).collect(), topic_input.split_whitespace().map(|inword| inword.to_string()).collect(), self.root.clone()).unwrap();
template
}
pub fn star(&mut self, star_type: String, pattern: String, that: String, topic: String, index: usize) -> String {
let mut pattern = pattern.clone();
let mut that = that.clone();
let mut topic = topic.clone();
let mut input: String = pattern.clone().to_uppercase().to_string();
input = self.punc_strip_re.replace_all(input.as_str(), " ").to_string();
input = self.whitespace_re.replace_all(input.as_str(), " ").to_string();
if that.trim().to_string() == String::new() {
that = "ULTRABOGUSDUMMYTOPIC".to_string();
}
let mut that_input: String = that.to_uppercase().to_string();
that_input = self.punc_strip_re.replace_all(that_input.as_str(), " ").to_string();
that_input = self.whitespace_re.replace_all(that_input.as_str(), " ").to_string();
if topic.trim().to_string() == String::new() {
topic = "ULTRABOGUSDUMMYTOPIC".to_string();
}
let mut topic_input: String = topic.to_uppercase().to_string();
topic_input = self.punc_strip_re.replace_all(topic_input.as_str(), " ").to_string();
topic_input = self.whitespace_re.replace_all(topic_input.as_str(), " ").to_string();
let (mut pat_match, mut template) = self._match(input.split_whitespace().map(|inword| inword.to_string()).collect(), that_input.split_whitespace().map(|inword| inword.to_string()).collect(), topic_input.split_whitespace().map(|inword| inword.to_string()).collect(), self.root.clone()).unwrap();
let mut words: Option<Vec<String>>;
if template.is_none() {
return String::new();
}
words = None;
let vec_pat_match: Vec<SonicSerdeObject> = pat_match.unwrap().collectvec().into_iter().map(|x| x.value.into()).collect();
if star_type.as_str() == "star" {
pat_match = Some(SonicObject::new(vec_pat_match.clone()[..vec_pat_match.clone().iter().position(|x| *x == SonicSerdeObject::U8(self.dict_that)).unwrap()].to_vec()));
words = Some(input.split_whitespace().map(|inword| inword.to_string()).collect());
} else if star_type.as_str() == "thatstar" {
pat_match = Some(SonicObject::new(vec_pat_match.clone()[(vec_pat_match.clone().iter().position(|x| *x == SonicSerdeObject::U8(self.dict_that)).unwrap() + 1)..(vec_pat_match.clone().iter().position(|x| *x == SonicSerdeObject::U8(self.dict_topic)).unwrap())].to_vec()));
words = Some(that_input.split_whitespace().map(|inword| inword.to_string()).collect());
} else if star_type.as_str() == "topicstar" {
pat_match = Some(SonicObject::new(vec_pat_match.clone()[(vec_pat_match.clone().iter().position(|x| *x == SonicSerdeObject::U8(self.dict_topic)).unwrap() + 1)..].to_vec()));
words = Some(topic_input.split_whitespace().map(|inword| inword.to_string()).collect());
} else {
panic!("Invalid star type: \"{}\"", star_type);
}
let mut found_right_star = false;
let mut start_: usize = 0;
let mut end: usize = 0;
let mut j = 0;
let mut num_stars = 0;
let mut k = 0;
for i in 0..(words.clone().unwrap().len()) {
if i < k {
continue;
}
if j == pat_match.clone().unwrap().value.as_vec().unwrap().len() { break;
}
if !found_right_star {
if vec![SonicSerdeObject::U8(self.dict_star), SonicSerdeObject::U8(self.dict_underscore)].contains(&pat_match.clone().unwrap().getindexvalue(j).unwrap()) {
num_stars = num_stars + 1;
if num_stars as usize == index {
found_right_star = true;
}
start_ = i.clone();
for k in i..(words.clone().unwrap().len()) {
if j + 1 == pat_match.clone().unwrap().collect::<Vec<SonicObject>>().len() {
end = words.clone().unwrap().len();
break;
}
if pat_match.as_ref().unwrap().getindexvalue(j + 1).unwrap().as_str().unwrap().to_string() == words.as_ref().unwrap()[k] {
end = k - 1;
break;
}
}
}
if found_right_star {
break;
}
}
j = j + 1;
}
if found_right_star {
if star_type.as_str() == "star" {
let a = pattern.split_whitespace().map(|inword| inword.to_string()).collect::<Vec<String>>(); let alen = a.len();
if end + 1 >= alen {
end = alen - 2;
}
return a[start_..=(end + 1)].join(" ");
} else if star_type.as_str() == "thatstar" {
let a = that.split_whitespace().map(|inword| inword.to_string()).collect::<Vec<String>>(); let alen = a.len();
if end + 1 >= alen {
end = alen - 2;
}
return a[start_..=(end + 1)].join(" ");
} else if star_type.as_str() == "thatstar" {
let a = topic.split_whitespace().map(|inword| inword.to_string()).collect::<Vec<String>>(); let alen = a.len();
if end + 1 >= alen {
end = alen - 2;
}
return a[start_..=(end + 1)].join(" ");
} else {
return String::new();
}
} else {
return String::new();
}
}
}