From edaa430edc2e7e691461b926305168ade85d389c Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:18:59 -0600 Subject: [PATCH 1/7] Expand FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 94 ++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index 92b19024..e3dd3d25 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -5,24 +5,96 @@ namespace DiscordBot.Data; +// A simple random string picking engine. +// +// Load it up like a list with string choices that can be picked from. +// Remember recently-picked choices so they don't repeat too soon. +// Individual string choices can also be evaluated with a simple syntax +// to further allow for alternative wordings, such as humanized messages. +// +// Evaluating "(He|She|They) (picked|chose) a (green|red|blue) (ball|block)." +// might return "She picked a red ball." +// public class FuzzTable { private static Random random = new(); private static Regex parenContents = null; private static TimeSpan timeout = new(10*10000/*x10nanoseconds*/); - //TODO: an instance keeps an array of alternates and an MRU list + private List choices = new(); + private Queue recent = new(); + + public void Clear() + { + choices.Clear(); + recent.Clear(); + } + + // Add a string as a valid choice from which to pick. + // Note that empty strings or whitespace can be added manually as valid choices. + // Duplicate choices are also allowed for weighting. + // + public void Add(string choice) + { + choices.Add(choice); + } + + // Load a file of string choices. + // Lines starting with a '#' character are ignored, as are blank lines. + // Each remaining line of the file is trimmed of leading and trailing whitespace. + // Each line is added as a new choice, and duplicates are allowed for weighting. + // + public void Load(string filename) + { + foreach (string line in File.ReadLines(filename)) + { + string choice = line.Trim(); + if (choice.StartsWith('#')) + continue; + Add(choice); + } + } + + // Pick one of the active choices. + // This choice is transferred to the MRU so it's not picked again too soon. + // If the evaluate flag is given, further Evaluate() it as a fuzz string. + // Returns the chosen results, or the empty string if no choices available. + // + public string Pick(bool evaluate=false) + { + Recycle(); + if (choices.Count == 0) + return ""; + int pick = random.Next(0, choices.Count); + string chosen = choices[pick]; + choices.RemoveAt(pick); + recent.Enqueue(chosen); + if (evaluate) + return Evaluate(chosen); + return chosen; + } + // When the MRU gets too long, return the oldest MRU choice(s) back + // to the active list of choices. + // + private void Recycle() + { + // Caps the MRU at half of total choices. + while (recent.Count > choices.Count) + { + string choice = recent.Dequeue(); + choices.Add(choice); + } + } + // Evaluate a single fuzz string. - // "(He|She|They) (picked|selected) a (green|red|blue) (ball|block)." - // "She picked a red ball." // Replace any parenthetical phrase with one of its choices at random. // Allows for nesting of choices. There's currently no way to escape // parentheses or vertical bars so strings must not include strays. // Returns one permutation from all choice alternatives given. - // Does not remember what choices were given. + // There is no MRU of individual permutations given. // - public static string Evaluate(string fuzz) + public static string Evaluate(string fuzz) { if (string.IsNullOrEmpty(fuzz)) return ""; @@ -36,15 +108,8 @@ public static string Evaluate(string fuzz) while (fuzz != before) { before = fuzz; - try - { - fuzz = parenContents.Replace(fuzz, - (m) => PickAlternate(m.Groups[1].ToString())); - } - catch (RegexMatchTimeoutException) - { - break; - } + fuzz = parenContents.Replace(fuzz, + (m) => PickAlternate(m.Groups[1].ToString())); } return fuzz; } @@ -61,3 +126,4 @@ private static string PickAlternate(string fuzz) } } + From 993e9b88f5a0460c4a69d718285d029bb957fcb2 Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:23:36 -0600 Subject: [PATCH 2/7] Update FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index e3dd3d25..bce690f0 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -108,8 +108,15 @@ public static string Evaluate(string fuzz) while (fuzz != before) { before = fuzz; - fuzz = parenContents.Replace(fuzz, - (m) => PickAlternate(m.Groups[1].ToString())); + try + { + fuzz = parenContents.Replace(fuzz, + (m) => PickAlternate(m.Groups[1].ToString())); + } + catch (RegexMatchTimeoutException) + { + break; + } } return fuzz; } From f2d2be74c91ff70e79597829844ffadb2a09132a Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:24:58 -0600 Subject: [PATCH 3/7] Update FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index bce690f0..4235c93f 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -1,6 +1,8 @@ // FuzzTable.cs // using System; +using System.IO; +using System.Collections.Generic; using System.Text.RegularExpressions; namespace DiscordBot.Data; From 0d513a320907ba5266f0f53425b05e9b9aa77025 Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:07:35 -0600 Subject: [PATCH 4/7] Update FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index 4235c93f..b620dcbd 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -32,6 +32,8 @@ public void Clear() recent.Clear(); } + public int Count => choices.Count + recent.Count; + // Add a string as a valid choice from which to pick. // Note that empty strings or whitespace can be added manually as valid choices. // Duplicate choices are also allowed for weighting. From e7feaf2b513538de92d06a7946bc83040ad1fa09 Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:15:27 -0600 Subject: [PATCH 5/7] Update FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index b620dcbd..b2e27c51 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -43,6 +43,16 @@ public void Add(string choice) choices.Add(choice); } + // Add a collection of choice strings all at once. + // + public void Add(IEnumerable newChoices) + { + if (newChoices == null) + return; + foreach (var addition in newChoices) + Add(addition); + } + // Load a file of string choices. // Lines starting with a '#' character are ignored, as are blank lines. // Each remaining line of the file is trimmed of leading and trailing whitespace. From ed29d14bf4e1306ca29e95deab380edbba1b696f Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:20:55 -0600 Subject: [PATCH 6/7] Update UserModule.cs --- DiscordBot/Modules/UserModule.cs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/DiscordBot/Modules/UserModule.cs b/DiscordBot/Modules/UserModule.cs index 9fe2994e..492a7410 100644 --- a/DiscordBot/Modules/UserModule.cs +++ b/DiscordBot/Modules/UserModule.cs @@ -9,6 +9,7 @@ using DiscordBot.Utils; using HtmlAgilityPack; using DiscordBot.Attributes; +using DiscordBot.Data; namespace DiscordBot.Modules; @@ -31,6 +32,8 @@ public class UserModule : ModuleBase #endregion private readonly Random _random = new(); + private FuzzTable _slapObjects = new(); + private FuzzTable _slapFails = new(); [Command("Help"), Priority(100)] [Summary("Does what you see now.")] @@ -624,10 +627,20 @@ public async Task SlapUser(params IUser[] users) var uname = Context.User.GetUserPreferredName(); - if (Settings.UserModuleSlapChoices == null || Settings.UserModuleSlapChoices.Count == 0) - Settings.UserModuleSlapChoices = new List() { "fish", "mallet" }; - if (Settings.UserModuleSlapFails == null || Settings.UserModuleSlapFails.Count == 0) - Settings.UserModuleSlapFails = new List() { "hurting themselves" }; + if (_slapObjects.Count == 0) + _slapObjects.Add(Settings.UserModuleSlapChoices); + if (_slapObjects.Count == 0) + _slapObjects.Add("fish|mallet"); + + if (_slapFails.Count == 0) + _slapFails.Add(Settings.UserModuleSlapFails); + if (_slapFails.Count == 0) + _slapFails.Add("hurting themselves"); + + // if (Settings.UserModuleSlapChoices == null || Settings.UserModuleSlapChoices.Count == 0) + // Settings.UserModuleSlapChoices = new List() { "fish", "mallet" }; + // if (Settings.UserModuleSlapFails == null || Settings.UserModuleSlapFails.Count == 0) + // Settings.UserModuleSlapFails = new List() { "hurting themselves" }; bool fail = (_random.Next(1, 100) < 5); @@ -642,9 +655,11 @@ public async Task SlapUser(params IUser[] users) if (fail) { sb.Append(" around a bit with a large "); - sb.Append(Settings.UserModuleSlapChoices[_random.Next() % Settings.UserModuleSlapChoices.Count]); + sb.Append(_slapObjects.Pick(true)); + //sb.Append(Settings.UserModuleSlapChoices[_random.Next() % Settings.UserModuleSlapChoices.Count]); sb.Append(", but misses and ends up "); - sb.Append(Settings.UserModuleSlapFails[_random.Next() % Settings.UserModuleSlapFails.Count]); + sb.Append(_slapFails.Pick(true)); + //sb.Append(Settings.UserModuleSlapFails[_random.Next() % Settings.UserModuleSlapFails.Count]); sb.Append("."); } else From 28816ba35fb095f8c996848462c021d1865a7c5b Mon Sep 17 00:00:00 2001 From: Ed Halley <1223980+hariedo@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:53:52 -0600 Subject: [PATCH 7/7] Update FuzzTable.cs --- DiscordBot/Data/FuzzTable.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DiscordBot/Data/FuzzTable.cs b/DiscordBot/Data/FuzzTable.cs index b2e27c51..05e0bc6a 100644 --- a/DiscordBot/Data/FuzzTable.cs +++ b/DiscordBot/Data/FuzzTable.cs @@ -45,12 +45,12 @@ public void Add(string choice) // Add a collection of choice strings all at once. // - public void Add(IEnumerable newChoices) + public void Add(IEnumerable stream) { - if (newChoices == null) + if (stream == null) return; - foreach (var addition in newChoices) - Add(addition); + foreach (var choice in stream) + Add(choice); } // Load a file of string choices.