[CanBeNull] private string Sentence([NotNull] ElizaContext ctx) { //Split sentence into words var words = ctx.Input.Split(' ', StringSplitOptions.RemoveEmptyEntries); //Check if there are any exit words, if so immediately terminate if (words.Any(_script.Quit.Contains)) { Finished = true; return _script.Final.Random(_random); } //Get key for each word in the sentence, ordered by rank var keys = from word in words from key in _script.GetKeys(word) where key != null orderby key.Rank descending select key; //Get a reply for each key var replies = from key in keys let reply = TryKey(key, new ElizaContext(ctx, ctx.Input.PadLeft(1).PadRight(1))) where reply != null select reply; //take the first non-null reply return replies.FirstOrDefault(); }
[CanBeNull] private string ProcessSentences([NotNull] ElizaContext ctx) { return (from sentence in ctx.Input.Split('.', StringSplitOptions.RemoveEmptyEntries) let transformed = new ElizaContext(ctx.Base, Transform(_script.Pre, sentence).Trim()) let r = Sentence(transformed) where r != null select r).FirstOrDefault(); }
[NotNull] public string ProcessInput([NotNull] ICommandContext input) { var ctx = new ElizaContext(input, CleanInput(input.Message.Content)); return ProcessSentences(ctx) //Try to create a reply to one of the sentences of the input ?? _mem.PopOrDefault() //Fall back to a reply we saved earlier ?? TryKey(_xnone.Random(_random), ctx) //Default reply ?? "I am at a loss for words"; //Return default default }
/// <summary>Decompose a string according to the given key.</summary> /// <remarks> /// Decompose a string according to the given key. Try each decomposition /// rule in order. If it matches, assemble a reply and return it. If assembly /// fails, try another decomposition rule. If assembly is a goto rule, return /// null and give the key. If assembly succeeds, return the reply; /// </remarks> [CanBeNull] private string TryKey([CanBeNull] Key key, ElizaContext ctx) { if (key == null) return null; //Select reassembly rules which match the input var decompositions = from decomp in key.Decompositions let decomposed = Patterns.Match(ctx.Input, decomp.Pattern, _script.Syns) where decomposed != null let rule = Task.Run(async () => await ChooseReassembly(decomp).Rule(ctx, decomposed)).Result where !string.IsNullOrWhiteSpace(rule) select (decomp, rule, decomposed); foreach (var (decomposition, rule, decomposed) in decompositions) { //If it's a goto rule follow it if (rule.StartsWith("goto ")) { var gotos = _script.GetKeys(rule.Substring(5)); return (from g in gotos orderby g.Rank descending let r = TryKey(g, ctx) where r != null select r).FirstOrDefault(); } //Try to assemble a reply using this reassembly rule var rep = Assemble(rule, decomposed); if (rep != null) { if (decomposition.Memorise) _mem.Push(rep); else return rep; } } return null; }