Getting started
Processing steps
The library uses three distinct steps to read EVTC logs and access data (with one exception, see below).
- Parsing (file → raw values in
ParsedLog
) –EVTCParser
- Processing (raw values in
ParsedLog
→ processed objects inLog
) –LogProcessor
- 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}.");
}