Skip to content

Commit

Permalink
Analytics: Initial support for WvW logs
Browse files Browse the repository at this point in the history
  • Loading branch information
Sejsel committed Aug 5, 2019
1 parent 34b5a00 commit 79d1d25
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 14 deletions.
35 changes: 23 additions & 12 deletions EVTCAnalytics/LogProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,31 @@ public Log GetProcessedLog(ParsedLog log)
var combatItemData = GetDataFromCombatItems(agents, skills, log);
var events = combatItemData.Events.ToArray();

Agent boss = null;
foreach (var agent in agents)
Agent mainTarget = null;
LogType logType = LogType.PvE;
if (log.ParsedBossData.ID != 1)
{
if (agent is NPC npc && npc.SpeciesId == log.ParsedBossData.ID ||
agent is Gadget gadget && gadget.VolatileId == log.ParsedBossData.ID)
foreach (var agent in agents)
{
boss = agent;
break;
if (agent is NPC npc && npc.SpeciesId == log.ParsedBossData.ID ||
agent is Gadget gadget && gadget.VolatileId == log.ParsedBossData.ID)
{
mainTarget = agent;
break;
}
}
}
else
{
logType = LogType.WorldVersusWorld;
}

SetAgentAwareTimes(events);
AssignAgentMasters(log, agents); // Needs to be done after setting aware times

return new Log(boss, events, agents, skills, log.LogVersion.BuildVersion, combatItemData.LogStartTime,
combatItemData.LogEndTime, combatItemData.PointOfView, combatItemData.Language,
combatItemData.GameBuild, combatItemData.GameShardId, combatItemData.MapId);
return new Log(mainTarget, logType, events, agents, skills, log.LogVersion.BuildVersion,
combatItemData.LogStartTime, combatItemData.LogEndTime, combatItemData.PointOfView,
combatItemData.Language, combatItemData.GameBuild, combatItemData.GameShardId, combatItemData.MapId);
}


Expand Down Expand Up @@ -122,10 +130,13 @@ private IEnumerable<Agent> GetAgents(ParsedLog log)
id = -1;
}

// All parts of the name of the player might not be available, most commonly in WvW logs.
var nameParts = agent.Name.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);
string characterName = nameParts[0];
string accountName = nameParts[1];
string subgroupLiteral = nameParts[2];
string accountName = nameParts.Length > 1 ? nameParts[1] : ":Unknown";
string subgroupLiteral = nameParts.Length > 2 ? nameParts[2] : "";
bool identified = nameParts.Length >= 3;

if (!int.TryParse(subgroupLiteral, out int subgroup))
{
subgroup = -1;
Expand All @@ -144,7 +155,7 @@ private IEnumerable<Agent> GetAgents(ParsedLog log)

yield return new Player(agent.Address, id, characterName, agent.Toughness, agent.Concentration,
agent.Healing, agent.Condition, agent.HitboxWidth, agent.HitboxHeight, accountName, profession,
specialization, subgroup);
specialization, subgroup, identified);
}
else
{
Expand Down
11 changes: 10 additions & 1 deletion EVTCAnalytics/Model/Agents/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ namespace GW2Scratch.EVTCAnalytics.Model.Agents
{
public class Player : Agent
{
/// <summary>
/// A value indicating whether all values are available. If false, <see cref="Agent.Name"/>,
/// <see cref="AccountName"/> and <see cref="Subgroup"/> will likely be random values. This
/// is most common in WvW on enemies as they are anonymized.
/// </summary>
public bool Identified { get; }

public string AccountName { get; }
public int Subgroup { get; }
public Profession Profession { get; }
Expand All @@ -13,14 +20,16 @@ public class Player : Agent
public byte[] GuildGuid { get; internal set; }

public Player(ulong address, int id, string name, int toughness, int concentration, int healing, int condition,
int hitboxWidth, int hitboxHeight, string accountName, Profession profession, EliteSpecialization eliteSpecialization, int subgroup)
int hitboxWidth, int hitboxHeight, string accountName, Profession profession,
EliteSpecialization eliteSpecialization, int subgroup, bool identified)
: base(address, id, name, hitboxWidth, hitboxHeight)
{
Toughness = toughness;
Concentration = concentration;
Healing = healing;
Condition = condition;

Identified = identified;
Subgroup = subgroup;
AccountName = accountName;
Profession = profession;
Expand Down
4 changes: 3 additions & 1 deletion EVTCAnalytics/Model/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ public class Log
public LogTime StartTime { get; }
public LogTime EndTime { get; }

public LogType LogType { get; }
public Agent MainTarget { get; }
public Player PointOfView { get; }
public int? Language { get; }
public int? GameBuild { get; }
public int? GameShardId { get; }
public int? MapId { get; }

public Log(Agent mainTarget, IEnumerable<Event> events, IEnumerable<Agent> agents,
public Log(Agent mainTarget, LogType logType, IEnumerable<Event> events, IEnumerable<Agent> agents,
IEnumerable<Skill> skills, string evtcVersion, LogTime startTime, LogTime endTime, Player pointOfView,
int? language, int? gameBuild, int? gameShardId, int? mapId)
{
MainTarget = mainTarget;
LogType = logType;
EVTCVersion = evtcVersion;
StartTime = startTime;
EndTime = endTime;
Expand Down
7 changes: 7 additions & 0 deletions EVTCAnalytics/Model/LogType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace GW2Scratch.EVTCAnalytics.Model
{
public enum LogType
{
PvE, WorldVersusWorld
}
}
18 changes: 18 additions & 0 deletions EVTCAnalytics/Statistics/EncounterFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ namespace GW2Scratch.EVTCAnalytics.Statistics
public class EncounterFinder : IEncounterFinder
{
public IEncounter GetEncounter(Log log)
{
switch (log.LogType)
{
case LogType.PvE:
return GetPvEEncounter(log);
case LogType.WorldVersusWorld:
return GetWvWEncounter(log);
default:
throw new ArgumentOutOfRangeException();
}
}

private IEncounter GetWvWEncounter(Log log)
{
return new WorldVersusWorldEncounter(log.Agents.OfType<Player>().Where(x => x.Subgroup == -1), log.Events);
}

private IEncounter GetPvEEncounter(Log log)
{
if (log.MainTarget is NPC boss)
{
Expand Down
23 changes: 23 additions & 0 deletions EVTCAnalytics/Statistics/Encounters/WorldVersusWorldEncounter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using GW2Scratch.EVTCAnalytics.Events;
using GW2Scratch.EVTCAnalytics.Model.Agents;
using GW2Scratch.EVTCAnalytics.Statistics.Encounters.Phases;
using GW2Scratch.EVTCAnalytics.Statistics.Encounters.Results;

namespace GW2Scratch.EVTCAnalytics.Statistics.Encounters
{
public class WorldVersusWorldEncounter : BaseEncounter
{
public IReadOnlyList<Player> Enemies { get; }

public WorldVersusWorldEncounter(IEnumerable<Player> enemies, IEnumerable<Event> events) :
base(Enumerable.Empty<Agent>(), events,
new PhaseSplitter(new StartTrigger(new PhaseDefinition("Combat"))),
new ConstantResultDeterminer(EncounterResult.Unknown),
new ConstantEncounterNameProvider("World versus World"))
{
Enemies = enemies.ToArray();
}
}
}

0 comments on commit 79d1d25

Please sign in to comment.