From f247f531fe4201199325b338956c5da4d56dd0c8 Mon Sep 17 00:00:00 2001 From: rasmus Date: Thu, 17 Apr 2025 22:17:57 +0200 Subject: [PATCH] General optimization and fixing. --- Tarpit/Tarpit/Program.cs | 45 +++++++---------- Tarpit/Tarpit/ServerUtils.cs | 91 ++++++++++++++++++++-------------- Tarpit/Tarpit/TagUtils.cs | 51 +++++++++++++++++++ Tarpit/Tarpit/Tarpit.csproj | 1 + Tarpit/Tarpit/WordPredictor.cs | 75 ---------------------------- Tarpit/Tarpit/WordUtils.cs | 63 +++++++++++++++++++++++ 6 files changed, 187 insertions(+), 139 deletions(-) create mode 100644 Tarpit/Tarpit/TagUtils.cs delete mode 100644 Tarpit/Tarpit/WordPredictor.cs create mode 100644 Tarpit/Tarpit/WordUtils.cs diff --git a/Tarpit/Tarpit/Program.cs b/Tarpit/Tarpit/Program.cs index 69ed1e8..d20ab6f 100644 --- a/Tarpit/Tarpit/Program.cs +++ b/Tarpit/Tarpit/Program.cs @@ -1,40 +1,31 @@ -using System.Diagnostics; +using System.Collections.Concurrent; using System.Net; using Tarpit; -/* -const string filePath = "/home/skingging/Documents/Projects/CSharp/AI-Tarpit/Tarpit/words/wordlist.txt"; -WordPredictor predictor = new(filePath); -string inputWord = Console.ReadLine() ?? string.Empty; -List predictedWord = predictor.PredictNextWord(inputWord.ToLower()); -*/ +const string filePath = "/home/skingging/Documents/Projects/CSharp/AI-Tarpit/Tarpit/words/wordlist.txt"; +WordUtils utils = new(); +Dictionary> words = WordUtils.LoadData(filePath); + +// TODO: Create a thread that continuously fills the queue, that can later be consumed by the server utils. +ConcurrentQueue tags = new(); +Thread createTags = new(() => TagUtils.CreateTags(tags, words)); +createTags.Start(); const string baseAddress = "http://localhost:10000/"; - -HttpListener listener = new(); -listener.Prefixes.Add(baseAddress); - -ServerUtils serverUtils = new(); - -try +while (true) { + HttpListener listener = new(); + listener.Prefixes.Add(baseAddress); listener.Start(); - Console.WriteLine("Listening on " + baseAddress); while (true) { HttpListenerContext context = await listener.GetContextAsync(); - await serverUtils.ProcessRequestAsync(context); + ServerUtils serverUtils = new(); + + Thread thread = new(() => _ = serverUtils.Serve(context, tags)); + thread.Start(); + //await serverUtils.Serve(context); } -} -catch (HttpListenerException ex) -{ - Console.WriteLine("Error starting or running the listener: " + ex.Message); - Console.WriteLine("Make sure you have the necessary permissions (requires running as administrator sometimes)"); -} -finally -{ - listener.Stop(); - listener.Close(); -} +} \ No newline at end of file diff --git a/Tarpit/Tarpit/ServerUtils.cs b/Tarpit/Tarpit/ServerUtils.cs index cef9691..184f6f5 100644 --- a/Tarpit/Tarpit/ServerUtils.cs +++ b/Tarpit/Tarpit/ServerUtils.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using System.Net; using System.Text; @@ -5,53 +6,69 @@ namespace Tarpit; public class ServerUtils { - private int _step = 0; + private const string BoilerplateHead = "\n\n\n\n\n\n \n\n Hello, world!\n\n \n\n \n\n \n\n"; + private const string BoilerplateBodyStart = ""; + private const string BoilerplateEnd = "\n\n"; - public async Task ProcessRequestAsync(HttpListenerContext context) + public async Task Serve(HttpListenerContext context, ConcurrentQueue tags) { - HttpListenerResponse response = context.Response; - - response.ContentType = "text/html; charset=utf-8"; - - Stream outputStream = response.OutputStream; + try + { + while (true) + { + await ProcessRequestAsync(context, tags); + } + } + catch (HttpListenerException ex) + { + Console.WriteLine(ex.Message); + } + } + + private async Task ProcessRequestAsync(HttpListenerContext context, ConcurrentQueue tags) + { + context.Response.ContentType = "text/html; charset=utf-8"; + Stream outputStream = context.Response.OutputStream; int i = 0; + string tag; while (true) { - byte[] buffer = Encoding.UTF8.GetBytes(GetNextHtmlChunk()); - await outputStream.WriteAsync(buffer, 0, buffer.Length); - await outputStream.FlushAsync(); + if (tags.IsEmpty) + { + continue; + } + + if (i == 0) + { + byte[] buffer = Encoding.UTF8.GetBytes(BoilerplateHead); + await outputStream.WriteAsync(buffer, 0, buffer.Length); + await outputStream.FlushAsync(); + } + + if (i == 1) + { + byte[] buffer = Encoding.UTF8.GetBytes(BoilerplateBodyStart); + await outputStream.WriteAsync(buffer, 0, buffer.Length); + await outputStream.FlushAsync(); + } + + if (tags.TryDequeue(out tag!)) + { + byte[] buffer = Encoding.UTF8.GetBytes(tag); + await outputStream.WriteAsync(buffer, 0, buffer.Length); + await outputStream.FlushAsync(); + } i++; + + Task.Delay(250).Wait(); } + byte[] temp = Encoding.UTF8.GetBytes(BoilerplateEnd); + await outputStream.WriteAsync(temp, 0, temp.Length); + await outputStream.FlushAsync(); + outputStream.Close(); } - - string GetNextHtmlChunk() - { - Task.Delay(1).Wait(); - - switch (_step) - { - case 0: - _step++; - return "Progressive HTML

Starting...

"; - case 1: - _step++; - return "

This is the first paragraph.

"; - case 2: - _step++; - return "

Here's another paragraph with some bold text.

"; - case 3: - _step++; - return "
  • Item 1
  • Item 2
"; - case 4: - _step++; - return "\"Placeholder"; - default: - _step = 0; - return ""; - } - } } \ No newline at end of file diff --git a/Tarpit/Tarpit/TagUtils.cs b/Tarpit/Tarpit/TagUtils.cs new file mode 100644 index 0000000..6dda555 --- /dev/null +++ b/Tarpit/Tarpit/TagUtils.cs @@ -0,0 +1,51 @@ +using System.Collections.Concurrent; +using System.Text; + +namespace Tarpit; + +public static class TagUtils +{ + public static void CreateTags(ConcurrentQueue tags, Dictionary> words) + { + string[] startWords = ["Andersen", "Denmark", "The", "Earth", "Who", "His", "Her", "Following", "At", "A"]; + List tagsList = []; + StringBuilder sb = new(); + + while (true) + { + if (tags.Count >= 100) + { + Thread.Sleep(100); + continue; + } + + tagsList.Add(startWords[Random.Shared.Next(startWords.Length - 1)]); + + for (int i = 0; i < 20; i++) + { + List temp = WordUtils.PredictNextWords(tagsList[i], words); + + if (temp.Count != 0) + { + tagsList.Add(temp[Random.Shared.Next(temp.Count - 1)]); + } + else + { + tagsList.Add(startWords[Random.Shared.Next(startWords.Length - 1)]); + } + } + + for (int i = 0; i < tagsList.Count; i++) + { + sb.Append(tagsList[i]); + sb.Append(' '); + } + + tags.Enqueue($"

{sb}

"); + + sb.Clear(); + + tagsList.Clear(); + } + } +} \ No newline at end of file diff --git a/Tarpit/Tarpit/Tarpit.csproj b/Tarpit/Tarpit/Tarpit.csproj index 85b4959..b52aae9 100644 --- a/Tarpit/Tarpit/Tarpit.csproj +++ b/Tarpit/Tarpit/Tarpit.csproj @@ -5,6 +5,7 @@ net9.0 enable enable + true diff --git a/Tarpit/Tarpit/WordPredictor.cs b/Tarpit/Tarpit/WordPredictor.cs deleted file mode 100644 index 39142d0..0000000 --- a/Tarpit/Tarpit/WordPredictor.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace Tarpit; - -public class WordPredictor -{ - private Dictionary> _wordFrequencies = new(); - - public WordPredictor(string filePath) - { - LoadData(filePath); - } - - private void LoadData(string filePath) - { - _wordFrequencies = new(); - - try - { - using StreamReader reader = new(filePath); - string? previousWord = null; - - while (reader.ReadLine() is { } line) - { - string[] words = line.Split(new char[] { ' ', '.', ',', '!', '?', ';', ':', '(', ')', '\n', '\r', '\t' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string word in words) - { - if (previousWord != null) - { - if (!_wordFrequencies.ContainsKey(previousWord)) - { - _wordFrequencies[previousWord] = []; - } - _wordFrequencies[previousWord].Add(word); - } - previousWord = word; - } - } - } - catch (FileNotFoundException) - { - Console.WriteLine($"Error: File not found at {filePath}"); - Environment.Exit(1); // Exit the program if the file isn't found. Important! - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred while reading the file: {ex.Message}"); - Environment.Exit(1); - } - } - - public List PredictNextWord(string inputWord) - { - if (!_wordFrequencies.ContainsKey(inputWord.ToLower())) - { - return ["Word not found in training data."]; - } - - List nextWords = _wordFrequencies[inputWord.ToLower()]; - - List words = []; - - for (int i = 0; i < 10; i++) - { - string? mostFrequentWord = nextWords - .GroupBy(w => w) - .OrderByDescending(g => g.Count()) - .ElementAtOrDefault(i) - ?.Key; - - words.Add(mostFrequentWord); - } - - return words; - } -} \ No newline at end of file diff --git a/Tarpit/Tarpit/WordUtils.cs b/Tarpit/Tarpit/WordUtils.cs new file mode 100644 index 0000000..5f795c6 --- /dev/null +++ b/Tarpit/Tarpit/WordUtils.cs @@ -0,0 +1,63 @@ +namespace Tarpit; + +public class WordUtils +{ + public static Dictionary> LoadData(string filePath) + { + Dictionary> wordFrequencies = new(); + + using StreamReader reader = new(filePath); + string? previousWord = null; + + while (reader.ReadLine() is { } line) + { + string[] words = line.Split(new char[] { ' ', '.', ',', '!', '?', ';', ':', '(', ')', '\n', '\r', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < words.Length; i++) + { + string word = words[i]; + if (previousWord != null) + { + if (!wordFrequencies.ContainsKey(previousWord)) + { + wordFrequencies[previousWord] = []; + } + + wordFrequencies[previousWord].Add(word); + } + + previousWord = word; + } + } + + return wordFrequencies; + } + + public static List PredictNextWords(string inputWord, Dictionary> wordFrequencies) + { + if (!wordFrequencies.ContainsKey(inputWord.ToLower())) + { + return [inputWord]; + } + + List nextWords = wordFrequencies[inputWord.ToLower()]; + + List words = []; + + for (int i = 0; i < 10; i++) + { + string? mostFrequentWord = nextWords + .GroupBy(w => w) + .OrderByDescending(g => g.Count()) + .ElementAtOrDefault(i) + ?.Key; + + if (!string.IsNullOrEmpty(mostFrequentWord)) + { + words.Add(mostFrequentWord); + } + } + + return words; + } +} \ No newline at end of file