예제 #1
0
        private static void MeasureTimes(string filename, EVTCParser parser, LogProcessor processor, GW2ApiData apiData, TextWriter outputWriter)
        {
            var stopwatch = Stopwatch.StartNew();
            var log       = parser.ParseLog(filename);

            var parsedTime = stopwatch.Elapsed;

            stopwatch.Restart();
            var processedLog = processor.ProcessLog(log);

            var processedTime = stopwatch.Elapsed;

            stopwatch.Restart();
            var analyzer = new LogAnalyzer(processedLog, apiData);
            var result   = analyzer.GetResult();
            var duration = analyzer.GetEncounterDuration();
            var mode     = analyzer.GetMode();

            var statisticsTime = stopwatch.Elapsed;

            var totalTime = parsedTime + processedTime + statisticsTime;

            outputWriter.WriteLine(
                $"{filename},{parsedTime.TotalMilliseconds},{processedTime.TotalMilliseconds},{statisticsTime.TotalMilliseconds},{totalTime.TotalMilliseconds}");
            outputWriter.Flush();
        }
예제 #2
0
        protected override Log GetLog()
        {
            if (processedLog == null)
            {
                var parser    = new EVTCParser();
                var processor = new LogProcessor();
                var parsedLog = parser.ParseLog(filename);
                processedLog = processor.ProcessLog(parsedLog);
            }

            return(processedLog);
        }
예제 #3
0
        static void Main()
        {
            string filename = "example.zevtc";

            var parser    = new EVTCParser();               // Used to read a log file and get raw data out of it
            var processor = new LogProcessor();             // Used to process the raw data

            // The parsed log contains raw data from the EVTC file
            ParsedLog parsedLog = parser.ParseLog(filename);

            // The log after processing the raw data into structured events and agents.
            Log log = processor.ProcessLog(parsedLog);

            // At this point, we can do anything with the processed data, and use the LogAnalyzer
            // for easy access to most common results with caching.
            var analyzer = new LogAnalyzer(log);

            Encounter encounter = analyzer.GetEncounter();

            // Encounter names are available for some languages, we use the target name if it's not.
            if (EncounterNames.TryGetEncounterNameForLanguage(GameLanguage.English, encounter, out string name))
            {
                Console.WriteLine($"Encounter: {name}");
            }
            else
            {
                Console.WriteLine($"Encounter: {log.MainTarget?.Name ?? "unknown target"}");
            }

            Console.WriteLine($"Result: {analyzer.GetResult()}");
            Console.WriteLine($"Mode: {analyzer.GetMode()}");
            Console.WriteLine($"Duration: {analyzer.GetEncounterDuration()}");

            // The processed log allows easy access to data about agents
            foreach (var player in log.Agents.OfType <Player>())
            {
                Console.WriteLine($"{player.Name} - {player.AccountName} - {player.Profession} - {player.EliteSpecialization}");
            }

            // Events may be accessed as well
            foreach (var deadEvent in log.Events.OfType <AgentDeadEvent>())
            {
                if (deadEvent.Agent is Player player)
                {
                    Console.WriteLine($"{player.Name} died at {deadEvent.Time}.");
                }
            }
        }
예제 #4
0
        protected override Log GetLog()
        {
            byte[] bytes;
            using (var memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);
                bytes = memoryStream.ToArray();
            }

            if (processedLog == null)
            {
                var parser    = new EVTCParser();
                var processor = new LogProcessor();
                var parsedLog = parser.ParseLog(bytes);
                processedLog = processor.ProcessLog(parsedLog);
            }

            return(processedLog);
        }
예제 #5
0
        public CheckResult CheckLog(string filename)
        {
            try
            {
                var parser    = new EVTCParser();
                var processor = new LogProcessor();

                var bytes = ReadLogFileBytes(filename);

                var parsedLog = parser.ParseLog(bytes);
                var log       = processor.ProcessLog(parsedLog);
                var analyzer  = new LogAnalyzer(log);

                var encounter = log.EncounterData.Encounter;
                var mode      = analyzer.GetMode();
                var result    = analyzer.GetResult();
                var players   = analyzer.GetPlayers()
                                .Select(p => new LogPlayer
                {
                    CharacterName       = p.Name,
                    AccountName         = p.AccountName,
                    Profession          = p.Profession,
                    EliteSpecialization = p.EliteSpecialization,
                    Subgroup            = p.Subgroup
                }).ToList();
                var duration = analyzer.GetEncounterDuration();

                // This combination of builds resulted in logs that did not contain NPCs other than the main target.
                // There is not much of a point in checking these.
                // This outdated version of arcdps was commonly used for extended periods of time due to it being
                // the last version that had working arcdps build templates.
                if (log.EvtcVersion == "EVTC20191001" && (log.GameBuild ?? 0) >= 100565)
                {
                    return(new CheckResult
                    {
                        Ignored = true,
                        Correct = false,
                        ProcessingFailed = false,
                        Encounter = Result <Encounter> .UncheckedResult(encounter),
                        Mode = Result <EncounterMode> .UncheckedResult(mode),
                        Result = Result <EncounterResult> .UncheckedResult(result),
                        Players = Result <List <LogPlayer> > .UncheckedResult(players),
                        Duration = Result <TimeSpan> .UncheckedResult(duration)
                    });
                }

                var eiSettings = new EvtcParserSettings(false, false, true, false, false, 0);
                var eiParser   = new EvtcParser(eiSettings, eiApiController);
                var eiLog      = eiParser.ParseLog(new EIController(), new MemoryStream(bytes), out var eiFailureReason);
                if (eiLog == null)
                {
                    eiFailureReason.Throw();
                }

                var eiDuration = TimeSpan.FromMilliseconds(eiLog.FightData.FightEnd - eiLog.FightData.FightStart);
                var eiResult   = eiLog.FightData.Success ? EncounterResult.Success : EncounterResult.Failure;
                var eiPlayers  = eiLog.PlayerList
                                 .Where(p => p.Prof != "Sword")
                                 .Select(p =>
                {
                    Profession profession;
                    if (Enum.TryParse(p.Prof, out EliteSpecialization specialization))
                    {
                        profession = GameData.Characters.GetProfession(specialization);
                    }
                    else
                    {
                        specialization = EliteSpecialization.None;
                        if (!Enum.TryParse(p.Prof, out profession))
                        {
                            throw new Exception($"Unknown profession {p.Prof} found in Elite Insights data.");
                        }
                    }

                    return(new LogPlayer
                    {
                        CharacterName = p.Character,
                        // EI strips the leading : in account names, so we re-add it
                        AccountName = $":{p.Account}",
                        Profession = profession,
                        EliteSpecialization = specialization,
                        Subgroup = p.Group
                    });
                }).ToList();

                var eiMode = eiLog.FightData.IsCM ? EncounterMode.Challenge : EncounterMode.Normal;

                // There is no reasonable way to compare EI and Analytics encounters
                var encounterResult = Result <Encounter> .UncheckedResult(encounter);

                var resultResult = CheckResult
                                        ? Result <EncounterResult> .CheckedResult(eiResult, result)
                                        : Result <EncounterResult> .UncheckedResult(result);

                var modeResult = CheckMode
                                        ? Result <EncounterMode> .CheckedResult(eiMode, mode)
                                        : Result <EncounterMode> .UncheckedResult(mode);

                var playerResult = CheckPlayers
                                        ? players.ToHashSet().SetEquals(eiPlayers)
                                                ? Result <List <LogPlayer> > .CorrectResult(players)
                                                : Result <List <LogPlayer> > .IncorrectResult(eiPlayers, players)
                                        : Result <List <LogPlayer> > .UncheckedResult(players);

                var durationResult = CheckDuration
                                        ? (eiDuration - duration) < DurationEpsilon
                                                ? Result <TimeSpan> .CorrectResult(duration)
                                                : Result <TimeSpan> .IncorrectResult(eiDuration, duration)
                                        : Result <TimeSpan> .UncheckedResult(duration);

                bool correct = encounterResult.Correct && resultResult.Correct && modeResult.Correct && playerResult.Correct && durationResult.Correct;

                return(new CheckResult
                {
                    Correct = correct,
                    ProcessingFailed = false,
                    Encounter = encounterResult,
                    Mode = modeResult,
                    Result = resultResult,
                    Players = playerResult,
                    Duration = durationResult
                });
            }
            catch (TooShortException)
            {
                return(new CheckResult
                {
                    Ignored = true,
                    Correct = false
                });
            }
            catch (Exception e)
            {
                return(new CheckResult
                {
                    Correct = false,
                    ProcessingFailed = true,
                    ProcessingException = e
                });
            }
        }
예제 #6
0
        public CheckResult CheckLog(LogDefinition definition)
        {
            try
            {
                var parser    = new EVTCParser();
                var processor = new LogProcessor();
                var parsedLog = parser.ParseLog(definition.Filename);
                var log       = processor.ProcessLog(parsedLog);
                var analyzer  = new LogAnalyzer(log);

                var encounter = log.EncounterData.Encounter;
                var mode      = analyzer.GetMode();
                var result    = analyzer.GetResult();
                var players   = analyzer.GetPlayers()
                                .Select(p => new LogPlayer
                {
                    CharacterName       = p.Name,
                    AccountName         = p.AccountName,
                    Profession          = p.Profession,
                    EliteSpecialization = p.EliteSpecialization,
                    Subgroup            = p.Subgroup
                }).ToList();

                var encounterResult = definition.Encounter.HasValue
                                        ? Result <Encounter> .CheckedResult(definition.Encounter.Value, encounter)
                                        : Result <Encounter> .UncheckedResult(encounter);

                var resultResult = definition.Result.HasValue
                                        ? Result <EncounterResult> .CheckedResult(definition.Result.Value, result)
                                        : Result <EncounterResult> .UncheckedResult(result);

                var modeResult = definition.Mode.HasValue
                                        ? Result <EncounterMode> .CheckedResult(definition.Mode.Value, mode)
                                        : Result <EncounterMode> .UncheckedResult(mode);

                var playerResult = definition.Players != null
                                        ? players.ToHashSet().SetEquals(definition.Players)
                                                ? Result <List <LogPlayer> > .CorrectResult(players)
                                                : Result <List <LogPlayer> > .IncorrectResult(definition.Players, players)
                                        : Result <List <LogPlayer> > .UncheckedResult(players);

                bool correct = encounterResult.Correct && resultResult.Correct && modeResult.Correct && playerResult.Correct;

                return(new CheckResult
                {
                    Correct = correct,
                    ProcessingFailed = false,
                    Encounter = encounterResult,
                    Mode = modeResult,
                    Result = resultResult,
                    Players = playerResult
                });
            }
            catch (Exception e)
            {
                return(new CheckResult
                {
                    Correct = false,
                    ProcessingFailed = true,
                    ProcessingException = e
                });
            }
        }
예제 #7
0
        } = null;                                                // TODO: Add support

        public MakerForm()
        {
            Title      = "Scratch HTML log maker";
            ClientSize = new Size(800, 600);
            var formLayout = new DynamicLayout();

            Content = formLayout;

            var openFileDialog = new OpenFileDialog {
                MultiSelect = true
            };

            openFileDialog.Filters.Add(new FileFilter("EVTC logs", ".evtc", ".evtc.zip", ".zevtc"));

            var openFilesButton = new Button {
                Text = "Select EVTC logs"
            };
            var processButton = new Button {
                Text = "Create HTML logs"
            };

            var notDoneListBox = new ListBox();
            var doneListBox    = new ListBox();

            doneListBox.DataStore = finishedFileNames.ToArray();

            var splitter = new Splitter {
                Panel1 = notDoneListBox, Panel2 = doneListBox, Position = 400
            };

            formLayout.BeginVertical(spacing: new Size(10, 10));
            formLayout.AddRow(openFilesButton, processButton);
            formLayout.EndVertical();
            formLayout.BeginVertical();
            formLayout.Add(splitter);
            formLayout.EndVertical();

            openFilesButton.Click += (sender, args) =>
            {
                if (openFileDialog.ShowDialog((Control)sender) == DialogResult.Ok)
                {
                    foreach (var file in openFileDialog.Filenames)
                    {
                        notFinishedFileNames.Enqueue(file);
                    }

                    notDoneListBox.DataStore = notFinishedFileNames.Select(Path.GetFileName).ToArray();
                }
            };

            processButton.Click += (sender, args) =>
            {
                Task.Run(() =>
                {
                    var times = new List <(string taskName, double milliseconds)>();
                    var totalTimeStopwatch = Stopwatch.StartNew();

                    var parser    = new EVTCParser();
                    var processor = new LogProcessor();
                    var generator = new HtmlGenerator(ApiData);

                    int finishedTaskCount = 0;
                    while (notFinishedFileNames.Count > 0)
                    {
                        var taskStopwatch = Stopwatch.StartNew();
                        string filename   = "";
                        filename          = notFinishedFileNames.Dequeue();

                        var fileDirectory = Path.GetDirectoryName(filename);
                        var newName       = Path.GetFileNameWithoutExtension(filename);
                        if (newName.EndsWith(".evtc"))
                        {
                            newName = newName.Substring(0, newName.Length - 5);
                        }
                        var resultFilename = Path.Combine(fileDirectory, ResultFilePrefix + newName + ".html");

                        try
                        {
                            var lastElapsed = taskStopwatch.Elapsed;

                            var parsedLog = parser.ParseLog(filename);
                            times.Add(("parsing", (taskStopwatch.Elapsed - lastElapsed).TotalMilliseconds));
                            lastElapsed = taskStopwatch.Elapsed;

                            var processedLog = processor.ProcessLog(parsedLog);
                            times.Add(("processing", (taskStopwatch.Elapsed - lastElapsed).TotalMilliseconds));
                            lastElapsed = taskStopwatch.Elapsed;

                            var analysis = new LogAnalyzer(processedLog, ApiData);
                            var stats    = analysis.GetStatistics();

                            times.Add(("stats", (taskStopwatch.Elapsed - lastElapsed).TotalMilliseconds));
                            lastElapsed = taskStopwatch.Elapsed;

                            using (var htmlStringWriter = new StreamWriter(resultFilename))
                            {
                                generator.WriteHtml(htmlStringWriter, stats);
                            }

                            times.Add(("html", (taskStopwatch.Elapsed - lastElapsed).TotalMilliseconds));
                            lastElapsed = taskStopwatch.Elapsed;

                            finishedFileNames.Add(resultFilename);
                            Application.Instance.Invoke(() =>
                            {
                                notDoneListBox.DataStore = notFinishedFileNames.Select(Path.GetFileName).ToArray();
                                doneListBox.DataStore    = finishedFileNames.Select(Path.GetFileName).ToArray();
                            });
                        }
                        catch (Exception e)
                        {
                            finishedFileNames.Add($"FAILED: {resultFilename} ({e.Message})");
                            Application.Instance.Invoke(() =>
                            {
                                notDoneListBox.DataStore = notFinishedFileNames.Select(Path.GetFileName).ToArray();
                                doneListBox.DataStore    = finishedFileNames.Select(Path.GetFileName).ToArray();
                            });
                        }
                        Console.WriteLine($"{newName} done, time {taskStopwatch.Elapsed}");
                        finishedTaskCount++;
                    }

                    Console.WriteLine($"All done, total time {totalTimeStopwatch.Elapsed}");

                    foreach ((string taskName, double totalMs) in times.GroupBy(x => x.taskName).Select(x => (x.Key, x.Sum(y => y.milliseconds))).OrderByDescending(x => x.Item2))
                    {
                        Console.WriteLine($"{taskName}, total {totalMs}ms, average {totalMs/Math.Max(finishedTaskCount, 1)}ms");
                    }
                });
            };
        }
예제 #8
0
        public void SelectLog(string logFilename)
        {
            var statusStringBuilder = new StringBuilder();

            var parser    = new EVTCParser();
            var processor = new LogProcessor()
            {
                IgnoreUnknownEvents = false
            };

            // Parsing
            var       sw        = Stopwatch.StartNew();
            ParsedLog parsedLog = null;

            try
            {
                parsedLog = parser.ParseLog(logFilename);
                var parseTime = sw.Elapsed;

                statusStringBuilder.AppendLine($"Parsed in {parseTime}");

                Application.Instance.Invoke(() =>
                {
                    parsedAgents.Clear();
                    parsedAgents.AddRange(parsedLog.ParsedAgents);
                    parsedAgents.Refresh();
                    parsedSkills.Clear();
                    parsedSkills.AddRange(parsedLog.ParsedSkills);
                    parsedSkills.Refresh();
                    parsedCombatItems.Clear();
                    parsedCombatItems.AddRange(parsedLog.ParsedCombatItems);
                    parsedCombatItems.Refresh();
                });
            }
            catch (Exception ex)
            {
                statusStringBuilder.AppendLine($"Parsing failed: {ex.Message}\n{ex.StackTrace}");
            }

            // Processing
            Log processedLog = null;

            try
            {
                sw.Restart();
                processedLog = processor.ProcessLog(parsedLog);
                var processTime = sw.Elapsed;

                statusStringBuilder.AppendLine($"Processed in {processTime}");

                Application.Instance.Invoke(() =>
                {
                    eventList.Clear();
                    eventList.AddRange(processedLog.Events);
                    eventListControl.Events = eventList;
                    eventListControl.Agents = processedLog.Agents.ToArray();
                    agents.Clear();
                    agents.AddRange(new FilterCollection <Agent>(processedLog.Agents));
                    agents.Refresh();
                    agentControl.Events = processedLog.Events.ToArray();
                });
            }
            catch (Exception ex)
            {
                statusStringBuilder.AppendLine($"Processing failed: {ex.Message}\n{ex.StackTrace}");
            }

            // Statistics
            Statistics stats = null;

            sw.Restart();
            try
            {
                var analyzer = new LogAnalyzer(processedLog);
                stats = new Statistics(processedLog.StartTime.LocalTime,
                                       processedLog.PointOfView,
                                       analyzer.GetResult(),
                                       analyzer.GetMode(),
                                       analyzer.GetEncounter(),
                                       processedLog.EvtcVersion,
                                       analyzer.GetEncounterDuration());

                var statsTime = sw.Elapsed;

                statusStringBuilder.AppendLine($"Statistics generated in {statsTime}");

                Application.Instance.Invoke(() => { statisticsJsonControl.Object = stats; });
            }
            catch (Exception ex)
            {
                statusStringBuilder.AppendLine($"Statistics generation failed: {ex.Message}\n{ex.StackTrace}");
            }

            Application.Instance.Invoke(() =>
            {
                statusStringBuilder.AppendLine(
                    $"Build version: {parsedLog?.LogVersion?.BuildVersion}, revision {parsedLog?.LogVersion?.Revision}");
                statusStringBuilder.AppendLine(
                    $"Parsed: {parsedLog?.ParsedAgents?.Count} agents, {parsedLog?.ParsedSkills?.Count} skills, {parsedLog?.ParsedCombatItems?.Count} combat items.");
                statusStringBuilder.AppendLine(
                    $"Processed: {processedLog?.Events?.Count} events, {processedLog?.Agents?.Count} agents.");
                parsedStateLabel.Text = statusStringBuilder.ToString();
            });
        }