Show / Hide Table of Contents

Getting started

Processing steps

The library uses three distinct steps to read EVTC logs and access data (with one exception, see below).

  1. Parsing (file → raw values in ParsedLog) – EVTCParser
  2. Processing (raw values in ParsedLog → processed objects in Log) – LogProcessor
  3. Analysis (processed objects in Log → results) – LogAnalyzer and custom analysis

Merging Parsing and Processing

The first two steps may also be done at once, which avoids unnecessary allocations if the ParsedLog is not needed. The LogProcessor provides overloads for directly going from files → Log.

Step 1: Parsing

This first step reads raw data from EVTC logs into Parsed objects, which contain raw values in a format very similar to the original structs used. The EVTCParser class is used for this, and the result is ParsedLog.

This is the last step at which data may be modified. The EVTCWriter may be used to write a (potentially modified) ParsedLog as an EVTC file.

Step 2: Processing

This step converts raw data from the parsing step into processed objects which only contain relevant values. The LogProcessor accepts a ParsedLog and produces an immutable Log with processed events, agents, and skills.

This is also the step at which the encounter is identified, but no analysis, such as success detection is made.

Step 3: Analysis

This step includes all actions done with the immutable Log object. The LogAnalyzer allows easy access to common statistics.

Example code

This is a short example of using the library. There is also a sample project available in the repository.

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}.");
}
  • Improve this Doc
In This Article
Back to top Generated by DocFX