public static ICollection <string> SortAtOnce(ICollection <string> unsorted) { var bucket = new Inheritance(); bucket.Fill(unsorted); return(bucket.Dump()); }
/// <summary> /// Sort the %Previous buffer. /// </summary> public void sortPrevious() { // Keep track if ANYTHING has a %Previous. _hasPrevious = false; // Find all the triggers that have a %Previous. This hash maps a %Previous // label to the list of triggers that are associated with it. var prev2trig = new Dictionary <string, ICollection <string> >(); // Loop through the triggers to find those with a %Previous. var triggers = listTriggers(true); for (int i = 0; i < triggers.Length; i++) { var pattern = triggers[i]; if (pattern.IndexOf("{previous}") > -1) { // This one has it. _hasPrevious = true; var parts = pattern.SplitRegex("\\{previous\\}", 2); var previous = parts[1]; // Keep it under the %Previous. if (false == prev2trig.ContainsKey(previous)) { prev2trig.Add(previous, new List <String>()); } prev2trig[previous].Add(parts[0]); } } // Loop over keys // TODO: Can do better to solve this, its is not best performance options // NOTE: ToArray is necessary to clone key list and avoid error on interation foreach (var key in prev2trig.Keys.ToArray()) { prev2trig[key] = Inheritance.SortAtOnce(prev2trig[key]); } this.previous = prev2trig; }
/// <summary> /// (Re)create the internal sort cache for this topic's triggers. /// </summary> /// <param name="alltrigs"></param> public void sortTriggers(string[] alltrigs) { // Get our list of triggers. var sorted = new List <string>(); // Do multiple sorts, one for each inheritence level. var heritage = new Dictionary <int, ICollection <string> >(); heritage.Add(-1, new List <string>()); var highest = -1; var reInherit = new Regex("\\{inherits=(\\d+)\\}"); for (int i = 0; i < alltrigs.Length; i++) { int inherits = -1; // Default, when no {inherits} tag. // Does it have an inherit level? if (alltrigs[i].IndexOf("{inherits=") > -1) { var mc = reInherit.Matches(alltrigs[i]); foreach (Match m in mc) { inherits = int.Parse(m.Groups[1].Value); if (inherits > highest) { highest = inherits; } break; } } alltrigs[i] = Regex.Replace(alltrigs[i], "\\{inherits=\\d+\\}", ""); // Initialize this inherit group? if (false == heritage.ContainsKey(inherits)) { heritage.Add(inherits, new List <string>()); } // Add it. heritage[inherits].Add(alltrigs[i]); } // Go on and sort each heritage level. We want to loop from level 0 up, // and then do level -1 last. for (int h = -1; h <= highest; h++) { if (false == heritage.ContainsKey(h)) { continue; } int inherits = h; say("Sorting triggers by heritage level " + inherits); var triggers = heritage[inherits].ToArray(); // Sort-priority maps. var prior = new Dictionary <int, ICollection <string> >(); // Assign each trigger to its priority level. say("BEGIN sortTriggers in topic " + this.name); var rePrior = new Regex("\\{weight=(\\d+?)\\}"); for (int i = 0; i < triggers.Length; i++) { int priority = 0; // See if this trigger has a {weight}. if (triggers[i].IndexOf("{weight") > -1) { //NOTE: I thnk this can do user only Match var mc = rePrior.Matches(triggers[i]); foreach (Match m in mc) { priority = int.Parse(m.Groups[1].Value); } } // Initialize its priority group? if (false == prior.ContainsKey(priority)) { // Create it. prior.Add(priority, new List <String>()); } // Add it. prior[priority].Add(triggers[i]); } /* * Keep in mind here that there is a difference between includes and * inherits -- topics that inherit other topics are able to OVERRIDE * triggers that appear in the inherited topic. This means that if the * top topic has a trigger of simply *, then NO triggers are capable of * matching in ANY inherited topic, because even though * has the lowest * sorting priority, it has an automatic priority over all inherited * topics. * * The topicTriggers in TopicManager takes this into account. All topics * that inherit other topics will have their local triggers prefixed * with a fictional {inherits} tag, which will start at {inherits=0} * and increment if the topic tree has other inheriting topics. So * we can use this tag to make sure topics that inherit things will * have their triggers always be on the top of the stack, from * inherits=0 to inherits=n. */ // Sort the priority lists numerically from highest to lowest. var prior_sorted = Util.SortKeysDesc(prior); for (int p = 0; p < prior_sorted.Length; p++) { say("Sorting triggers w/ priority " + prior_sorted[p]); var p_list = prior[prior_sorted[p]]; /* * So, some of these triggers may include {inherits} tags, if * they came from a topic which inherits another topic. Lower * inherits values mean higher priority on the stack. Keep this * in mind when keeping track of how to sort these things. */ var highest_inherits = inherits; // highest {inherits} we've seen // Initialize a sort bucket that will keep inheritance levels' // triggers in separate places. //com.rivescript.InheritanceManager bucket = new com.rivescript.InheritanceManager(); var bucket = new Inheritance(); // Loop through the triggers and sort them into their buckets. foreach (var e in p_list) { var trigger = e.ToString(); //Copy the element // Count the number of whole words it has. //Javacode: String[] words = trigger.split("[ |\\*|\\#|\\_]"); var words = Regex.Split(trigger, "[ |\\*|\\#|_]"); int wc = 0; for (int w = 0; w < words.Length; w++) { if (words[w].Length > 0) { wc++; } } say("On trigger: " + trigger + " (it has " + wc + " words) - inherit level: " + inherits); // Profile it. if (trigger.IndexOf("_") > -1) { // It has the alpha wildcard, _. if (wc > 0) { bucket.addAlpha(wc, trigger); } else { bucket.addUnder(trigger); } } else if (trigger.IndexOf("#") > -1) { // It has the numeric wildcard, #. if (wc > 0) { bucket.addNumber(wc, trigger); } else { bucket.addPound(trigger); } } else if (trigger.IndexOf("*") > -1) { // It has the global wildcard, *. if (wc > 0) { bucket.addWild(wc, trigger); } else { bucket.addStar(trigger); } } else if (trigger.IndexOf("[") > -1) { // It has optional parts. bucket.addOption(wc, trigger); } else { // Totally atomic. bucket.addAtomic(wc, trigger); } } // Sort each inheritence level individually. say("Dumping sort bucket !"); var subsort = bucket.Dump(new List <string>()); foreach (var item in subsort) { say("ADD TO SORT: " + item); sorted.Add(item); } } } // Turn the running sort buffer into a string array and store it. this.sorted = sorted.ToArray(); }
/// <summary> /// (Re)create the internal sort cache for this topic's triggers. /// </summary> /// <param name="alltrigs"></param> public void sortTriggers(string[] alltrigs) { // Get our list of triggers. var sorted = new List <string>(); // Do multiple sorts, one for each inheritence level. var heritage = new Dictionary <int, ICollection <string> >(); heritage.Add(-1, new List <string>()); var highest = -1; var reInherit = new Regex("\\{inherits=(\\d+)\\}"); for (int i = 0; i < alltrigs.Length; i++) { int inherits = -1; // Default, when no {inherits} tag. // Does it have an inherit level? if (alltrigs[i].IndexOf("{inherits=") > -1) { var mc = reInherit.Matches(alltrigs[i]); foreach (Match m in mc) { inherits = int.Parse(m.Groups[1].Value); if (inherits > highest) { highest = inherits; } break; } } alltrigs[i] = Regex.Replace(alltrigs[i], "\\{inherits=\\d+\\}", ""); // Initialize this inherit group? if (false == heritage.ContainsKey(inherits)) { heritage.Add(inherits, new List <string>()); } // Add it. heritage[inherits].Add(alltrigs[i]); } // Move the no-{inherits} triggers to the bottom of the stack. heritage.Add(highest + 1, heritage[-1]); heritage.Remove(-1); // Go on and sort each heritage level. We want to loop from level 0 up, for (int h = 0; h <= highest + 1; h++) { if (false == heritage.ContainsKey(h)) { continue; } int inherits = h; say("Sorting triggers by heritage level " + inherits); var triggers = heritage[inherits].ToArray(); // Sort-priority maps. var prior = new Dictionary <int, ICollection <string> >(); // Assign each trigger to its priority level. say("BEGIN sortTriggers in topic " + this.name); var rePrior = new Regex("\\{weight=(\\d+?)\\}"); for (int i = 0; i < triggers.Length; i++) { int priority = 0; // See if this trigger has a {weight}. if (triggers[i].IndexOf("{weight") > -1) { //NOTE: I thnk this can do user only Match var mc = rePrior.Matches(triggers[i]); foreach (Match m in mc) { priority = int.Parse(m.Groups[1].Value); } } // Initialize its priority group? if (false == prior.ContainsKey(priority)) { // Create it. prior.Add(priority, new List <String>()); } // Add it. prior[priority].Add(triggers[i]); } /* * Keep in mind here that there is a difference between includes and * inherits -- topics that inherit other topics are able to OVERRIDE * triggers that appear in the inherited topic. This means that if the * top topic has a trigger of simply *, then NO triggers are capable of * matching in ANY inherited topic, because even though * has the lowest * sorting priority, it has an automatic priority over all inherited * topics. * * The topicTriggers in TopicManager takes this into account. All topics * that inherit other topics will have their local triggers prefixed * with a fictional {inherits} tag, which will start at {inherits=0} * and increment if the topic tree has other inheriting topics. So * we can use this tag to make sure topics that inherit things will * have their triggers always be on the top of the stack, from * inherits=0 to inherits=n. */ // Sort the priority lists numerically from highest to lowest. var prior_sorted = Util.SortKeysDesc(prior); for (int p = 0; p < prior_sorted.Length; p++) { say("Sorting triggers w/ priority " + prior_sorted[p]); var p_list = prior[prior_sorted[p]]; /* * So, some of these triggers may include {inherits} tags, if * they came from a topic which inherits another topic. Lower * inherits values mean higher priority on the stack. Keep this * in mind when keeping track of how to sort these things. */ // Initialize a sort bucket that will keep inheritance levels' // triggers in separate places. //com.rivescript.InheritanceManager bucket = new com.rivescript.InheritanceManager(); var bucket = new Inheritance(); // Loop through the triggers and sort them into their buckets. bucket.Fill(p_list); // Sort each inheritence level individually. say("Dumping sort bucket !"); var subsort = bucket.Dump(); foreach (var item in subsort) { say("ADD TO SORT: " + item); sorted.Add(item); } } } // Turn the running sort buffer into a string array and store it. this.sorted = sorted.ToArray(); }