예제 #1
0
        public static void MineStatusLogs()
        {
            var filename = "./Log_2021-06-07 18-50-31.csv";

            var logLines = LoadLog(filename);

            var maybeStatusLines = logLines
                                   .Where(line => line.MessageType == CsvLogFileWriter.LOG_TYPE_MUD_OUTPUT && line.Text.Contains(" >"))
                                   .Select(line => ControlCharacterEncoder.Encode(line.Text, forCsv: true))
                                   .ToList();


            var grouped = maybeStatusLines
                          .GroupBy(sl => sl)
                          .OrderByDescending(group => group.Count())
                          .Select((group) => $"{group.Count()}, {group.Key}");


            // File.WriteAllLines("./minedStatusLines.txt", grouped);


            var splitLinedStatusLines = maybeStatusLines.Select(msl => msl.Replace("\\r\\n", "\n").Split('\n')).SelectMany(m => m).ToList();

            var x = splitLinedStatusLines.Where(line => line.Contains(" >")).ToList();

            var y = x.Where(s => s.StartsWith("o") || s.StartsWith("*")).Distinct().ToList();
            var z = x.Where(s => !s.StartsWith("o") && !s.StartsWith("*")).ToList();

            File.WriteAllLines("./splitMinedStatusLines.txt", y);

            var i = 0;
        }
예제 #2
0
 private LogLine ToLogLine(string output, string messageType)
 {
     return(new LogLine {
         Time = DateTime.Now,
         MsSinceStart = _sw.Elapsed.TotalMilliseconds,
         MessageType = messageType,
         EncodedText = ControlCharacterEncoder.Encode(output, forCsv: true),
     });
 }
        private async Task ProcessLogLoop(string filename, TimeSpan timeBetweenMessages, Action onLogParsed, CancellationToken cancellationToken)
        {
            var lines = File.ReadAllLines(filename);

            await Task.Delay(_initialDelay); // todo: dirty hack because the windows need to be load before the log starts flying

            foreach (var line in lines)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                // convert the line from csv into data
                var splitLine = line.Split(',');

                var logLine = new LogLine {
                    Time         = DateTime.Parse(splitLine[0]),
                    MsSinceStart = double.Parse(splitLine[1]),
                    MessageType  = splitLine[2],
                    EncodedText  = splitLine[3]
                };

                await Task.Delay(timeBetweenMessages);

                string decodedText = ControlCharacterEncoder.Decode(logLine.EncodedText);

                if (logLine.MessageType == LOG_TYPE_MUD_INPUT)
                {
                    await Store.TcpSend.SendAsync(decodedText);
                }
                else if (logLine.MessageType == LOG_TYPE_MUD_OUTPUT)
                {
                    await Store.TcpReceive.SendAsync(decodedText);
                }
                else if (logLine.MessageType == LOG_TYPE_CLIENT_INFO)
                {
                    await Store.ClientInfo.SendAsync(decodedText);
                }
                else
                {
                    throw new Exception("unknown log message type");
                }
            }
            if (onLogParsed != null)
            {
                onLogParsed();
            }
        }
예제 #4
0
        public static List <LogMiner.LogLine> LoadLog(string filename)
        {
            var lines = File.ReadAllLines(filename);

            return(lines.Select((line) => {
                var splitLine = line.Split(',');

                return new LogMiner.LogLine {
                    Time = DateTime.Parse(splitLine[0]),
                    MsSinceStart = double.Parse(splitLine[1]),
                    MessageType = splitLine[2],
                    Text = ControlCharacterEncoder.Decode(splitLine[3]),
                };
            }).ToList());
        }
        public ParsedOutputConverter()
        {
            var simpleParser = new SimpleParser();
            var attackParser = new AttackParser();
            var narrsParser  = new NarrsParser();

            Store.TcpReceive.SubscribeAsync(async(message) => {
                var lines = ControlCharacterEncoder.EncodeAndSplit(message);


                var parsedWithStatusSeparate        = new StatusParser().Parse(lines);
                var parsedWithStatusAndRoomSeparate = RoomParser.Parse(parsedWithStatusSeparate);

                foreach (var output in parsedWithStatusAndRoomSeparate)
                {
                    if (output.Type != ParsedOutputType.Raw)
                    {
                        continue;
                    }

                    output.LineMetadata = new LineMetadata[output.Lines.Length];

                    int i = 0;
                    foreach (var line in output.Lines)
                    {
                        // todo: is having a separate lineMetadata array the way to go? it minimizes copies a little bit but it's ugly and also in some ways doesnt
                        output.LineMetadata[i] = new LineMetadata();
                        var result             = simpleParser.Parse(line);
                        if (result != LineMetadataType.None)
                        {
                            output.LineMetadata[i].Type = result;
                        }
                        else if (attackParser.Matches(line))
                        {
                            output.LineMetadata[i].Type = LineMetadataType.Attack;
                        }
                        else if (narrsParser.Matches(line))
                        {
                            output.LineMetadata[i].Type = LineMetadataType.Communication;
                        }
                        i++;
                    }
                }
                await Store.ParsedOutput.SendAsync(parsedWithStatusAndRoomSeparate);
            });
        }
예제 #6
0
        public StatusWriter(StatusForm statusForm)
        {
            var scoreHealthRegex = new Regex(@"^You have (\d*)\((\d*)\) hit(, (\d*)\((\d*)\) (saidin|saidar|dark power))? and (-?\d*)\((\d*)\) movement points.$", RegexOptions.Compiled);

            var enemyColors = new Regex(@"\*\\x1B\[3(6|5|1)m([^ ]*)\\x1B\[0m\*", RegexOptions.Compiled);

            Store.ParsedOutput.Subscribe((outputs) => {
                foreach (var output in outputs)
                {
                    if (output.Type == ParsedOutputType.Raw)
                    {
                        foreach (var line in output.Lines)
                        {
                            if (scoreHealthRegex.IsMatch(line))
                            {
                                statusForm.WriteToOutput(line + "\n", MudColors.ForegroundColor);
                            }
                            if (enemyColors.IsMatch(line))
                            {
                                // todo: this is inefficient
                                statusForm.WriteToOutput(FormatDecodedText.Format(ControlCharacterEncoder.Decode(line + "\n")));
                            }
                        }
                    }
                    else if (output.Type == ParsedOutputType.Status)
                    {
                        statusForm.WriteToOutput(output.Lines[0] + "\n", MudColors.ForegroundColor);
                    }
                    else if (output.Type == ParsedOutputType.Room)
                    {
                        foreach (var line in output.Creatures)
                        {
                            if (enemyColors.IsMatch(line))
                            {
                                // todo: this is inefficient
                                statusForm.WriteToOutput(FormatDecodedText.Format(ControlCharacterEncoder.Decode(line + "\n")));
                            }
                        }
                    }
                }
            });
        }
예제 #7
0
        public NarrsWriter(MudClientForm form)
        {
            _form = form;

            Store.ParsedOutput.Subscribe((outputs) => {
                foreach (var output in outputs)
                {
                    if (output.Type != ParsedOutputType.Raw)
                    {
                        continue;
                    }
                    foreach (var line in output.Lines)
                    {
                        // todo: also include my narrates in here
                        // todo: should match on colour and also with a regex instead of doing this
                        if (line.Contains(" narrates '") ||
                            line.Contains(" tells you '") ||
                            line.Contains(" says '") ||
                            line.Contains(" speaks from the ") ||
                            line.Contains(" bellows '") ||
                            line.Contains(" hisses '") ||
                            line.Contains(" chats '") ||
                            line == "You are hungry." ||
                            line == "You are thirsty.")
                        {
                            if (line == "You are hungry." || line == "You are thirsty.")
                            {
                                SystemSounds.Beep.Play();
                            }


                            // todo: decoding & then converting to rich text will be needlessly wasteful
                            _form.WriteToNarrs(FormatDecodedText.Format(ControlCharacterEncoder.Decode(line + "\n")));
                        }
                    }
                }
            });
        }
예제 #8
0
        public static void MineAttackLogs()
        {
            var r = new Regex(" (blast|cleave|crush|hack|hit|lance|pierce|pound|scythe|shoot|slash|slice|smite|stab|sting|strike|whip)");

            var filename = "./Log_2021-06-12 12-52-06.csv";

            var logLines = LoadLog(filename);


            var matches = logLines
                          .Where(line => line.MessageType == CsvLogFileWriter.LOG_TYPE_MUD_OUTPUT)
                          .Select(l => l.Text.Replace("\\r\\n", "\n").Replace("\\r", "").Split('\n')).SelectMany(m => m)
                          .Where(line => r.IsMatch(line))
                          .Select(line => ControlCharacterEncoder.Encode(line, forCsv: true))
                          .GroupBy(l => l)
                          .OrderByDescending(g => g.Key)
                          .OrderByDescending(group => group.Count())
                          .Select(g => $"{g.Count()}, {g.Key}")
                          .ToList();


            File.WriteAllLines("./AttackLines.txt", matches);
        }
예제 #9
0
        public ParsedOutputWriter(MudClientForm form)
        {
            Store.TcpSend.Subscribe((message) => {
                // output = output + "\n"; // seems to be the most like zMud
                form.WriteToOutput(" " + message + " ", MudColors.CommandColor);
            });

            Store.ClientInfo.Subscribe((message) => {
                form.WriteToOutput("\n" + message + "\n", MudColors.ClientInfoColor);
            });


            Store.ParsedOutput.Subscribe((parsedOutputs) => {
                foreach (var p in parsedOutputs)
                {
                    switch (p.Type)
                    {
                    case ParsedOutputType.Raw:
                        // todo: dont unsplit things, dont decode things ~ waste of time & effort
                        // probably copy paste a custom version of .FormatOutput

                        /*var lines = p.Lines;
                         * for (int i = 0; i < p.Lines.Length; i++) {
                         *  if (!string.IsNullOrWhiteSpace(p.Lines[i])) {
                         *      lines[i] = p.LineMetadata[i].Type.ToString().PadRight(15)[..15] + " " + p.Lines[i];
                         *  }
                         * }*/

                        var formattedOutput = FormatDecodedText.Format(ControlCharacterEncoder.Decode(string.Join("\n", p.Lines) + "\n"));
                        form.WriteToOutput(formattedOutput);

                        if (!form.ContainsFocus)
                        {
                            WindowFlasher.Flash(form);
                        }
                        break;

                    case ParsedOutputType.Room:
                        // todo: there's a break between rooms even if it was a dline

                        form.WriteToOutput("\n" + p.Title, MudColors.RoomTitle);
                        // form.WriteToOutput(string.Join("\n", p.Description) + "\n", MudColors.ForegroundColor);
                        form.WriteToOutput(p.Exits + "\n", MudColors.RoomExits);
                        if (p.Tracks.Length > 0)
                        {
                            form.WriteToOutput(string.Join("\n", p.Tracks) + "\n", MudColors.Tracks);
                        }
                        if (p.Items.Length > 0)
                        {
                            form.WriteToOutput(string.Join("\n", p.Items) + "\n", MudColors.ItemsOnFloor);
                        }
                        if (p.Creatures.Length > 0)
                        {
                            // Todo: does this work correctly? also it's inefficient
                            form.WriteToOutput(FormatDecodedText.Format(ControlCharacterEncoder.Decode("\\x1B[33m" + string.Join("\n", p.Creatures) + "\n")));
                        }

                        break;

                    case ParsedOutputType.Status:
                        form.WriteToOutput(p.Lines[0] + " ", MudColors.ForegroundColor);
                        break;

                    default:
                        throw new Exception("Unhandled parsed output type");
                    }
                }
            });
        }