public static JsonPlayer BuildJsonPlayer(Player player, ParsedEvtcLog log, RawFormatSettings settings, Dictionary <string, JsonLog.SkillDesc> skillDesc, Dictionary <string, JsonLog.BuffDesc> buffDesc, Dictionary <string, JsonLog.DamageModDesc> damageModDesc, Dictionary <string, HashSet <long> > personalBuffs)
        {
            var jsonPlayer = new JsonPlayer();

            JsonActorBuilder.FillJsonActor(jsonPlayer, player, log, settings, skillDesc, buffDesc);
            IReadOnlyList <PhaseData> phases = log.FightData.GetNonDummyPhases(log);

            //
            jsonPlayer.Account         = player.Account;
            jsonPlayer.Weapons         = player.GetWeaponsArray(log).Select(w => w ?? "Unknown").ToArray();
            jsonPlayer.Group           = player.Group;
            jsonPlayer.Profession      = player.Prof;
            jsonPlayer.FriendlyNPC     = player.AgentItem.IsNPC;
            jsonPlayer.NotInSquad      = player.AgentItem.IsNotInSquadPlayer;
            jsonPlayer.ActiveTimes     = phases.Select(x => player.GetActiveDuration(log, x.Start, x.End)).ToList();
            jsonPlayer.HasCommanderTag = player.HasCommanderTag;
            //
            jsonPlayer.Support = phases.Select(phase => JsonStatisticsBuilder.BuildJsonPlayerSupport(player.GetPlayerSupportStats(log, phase.Start, phase.End))).ToArray();
            var targetDamage1S          = new IReadOnlyList <int> [log.FightData.Logic.Targets.Count][];
            var targetPowerDamage1S     = new IReadOnlyList <int> [log.FightData.Logic.Targets.Count][];
            var targetConditionDamage1S = new IReadOnlyList <int> [log.FightData.Logic.Targets.Count][];
            var targetBreakbarDamage1S  = new IReadOnlyList <double> [log.FightData.Logic.Targets.Count][];
            var dpsTargets       = new JsonStatistics.JsonDPS[log.FightData.Logic.Targets.Count][];
            var statsTargets     = new JsonStatistics.JsonGameplayStats[log.FightData.Logic.Targets.Count][];
            var targetDamageDist = new IReadOnlyList <JsonDamageDist> [log.FightData.Logic.Targets.Count][];

            for (int j = 0; j < log.FightData.Logic.Targets.Count; j++)
            {
                NPC target                     = log.FightData.Logic.Targets[j];
                var graph1SDamageList          = new IReadOnlyList <int> [phases.Count];
                var graph1SPowerDamageList     = new IReadOnlyList <int> [phases.Count];
                var graph1SConditionDamageList = new IReadOnlyList <int> [phases.Count];
                var graph1SBreakbarDamageList  = new IReadOnlyList <double> [phases.Count];
                var targetDamageDistList       = new IReadOnlyList <JsonDamageDist> [phases.Count];
                for (int i = 0; i < phases.Count; i++)
                {
                    PhaseData phase = phases[i];
                    if (settings.RawFormatTimelineArrays)
                    {
                        graph1SDamageList[i]          = player.Get1SDamageList(log, phase.Start, phase.End, target, DamageType.All);
                        graph1SPowerDamageList[i]     = player.Get1SDamageList(log, phase.Start, phase.End, target, DamageType.Power);
                        graph1SConditionDamageList[i] = player.Get1SDamageList(log, phase.Start, phase.End, target, DamageType.Condition);
                        graph1SBreakbarDamageList[i]  = player.Get1SBreakbarDamageList(log, phase.Start, phase.End, target);
                    }
                    targetDamageDistList[i] = JsonDamageDistBuilder.BuildJsonDamageDistList(player.GetDamageEvents(target, log, phase.Start, phase.End).GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList()), log, skillDesc, buffDesc);
                }
                if (settings.RawFormatTimelineArrays)
                {
                    targetDamage1S[j]          = graph1SDamageList;
                    targetPowerDamage1S[j]     = graph1SPowerDamageList;
                    targetConditionDamage1S[j] = graph1SConditionDamageList;
                    targetBreakbarDamage1S[j]  = graph1SBreakbarDamageList;
                }
                targetDamageDist[j] = targetDamageDistList;
                dpsTargets[j]       = phases.Select(phase => JsonStatisticsBuilder.BuildJsonDPS(player.GetDPSStats(target, log, phase.Start, phase.End))).ToArray();
                statsTargets[j]     = phases.Select(phase => JsonStatisticsBuilder.BuildJsonGameplayStats(player.GetGameplayStats(target, log, phase.Start, phase.End))).ToArray();
            }
            if (settings.RawFormatTimelineArrays)
            {
                jsonPlayer.TargetDamage1S          = targetDamage1S;
                jsonPlayer.TargetPowerDamage1S     = targetPowerDamage1S;
                jsonPlayer.TargetConditionDamage1S = targetConditionDamage1S;
                jsonPlayer.TargetBreakbarDamage1S  = targetBreakbarDamage1S;
            }
            jsonPlayer.TargetDamageDist = targetDamageDist;
            jsonPlayer.DpsTargets       = dpsTargets;
            jsonPlayer.StatsTargets     = statsTargets;
            if (!log.CombatData.HasBreakbarDamageData)
            {
                jsonPlayer.TargetBreakbarDamage1S = null;
            }
            //
            jsonPlayer.BuffUptimes   = GetPlayerJsonBuffsUptime(player, phases.Select(phase => player.GetBuffs(BuffEnum.Self, log, phase.Start, phase.End)).ToList(), log, settings, buffDesc, personalBuffs);
            jsonPlayer.SelfBuffs     = GetPlayerBuffGenerations(phases.Select(phase => player.GetBuffs(BuffEnum.Self, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.GroupBuffs    = GetPlayerBuffGenerations(phases.Select(phase => player.GetBuffs(BuffEnum.Group, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.OffGroupBuffs = GetPlayerBuffGenerations(phases.Select(phase => player.GetBuffs(BuffEnum.OffGroup, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.SquadBuffs    = GetPlayerBuffGenerations(phases.Select(phase => player.GetBuffs(BuffEnum.Squad, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            //
            jsonPlayer.BuffUptimesActive   = GetPlayerJsonBuffsUptime(player, phases.Select(phase => player.GetActiveBuffs(BuffEnum.Self, log, phase.Start, phase.End)).ToList(), log, settings, buffDesc, personalBuffs);
            jsonPlayer.SelfBuffsActive     = GetPlayerBuffGenerations(phases.Select(phase => player.GetActiveBuffs(BuffEnum.Self, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.GroupBuffsActive    = GetPlayerBuffGenerations(phases.Select(phase => player.GetActiveBuffs(BuffEnum.Group, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.OffGroupBuffsActive = GetPlayerBuffGenerations(phases.Select(phase => player.GetActiveBuffs(BuffEnum.OffGroup, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            jsonPlayer.SquadBuffsActive    = GetPlayerBuffGenerations(phases.Select(phase => player.GetActiveBuffs(BuffEnum.Squad, log, phase.Start, phase.End)).ToList(), log, buffDesc);
            //
            IReadOnlyList <Consumable> consumables = player.GetConsumablesList(log, 0, log.FightData.FightEnd);

            if (consumables.Any())
            {
                var consumablesJSON = new List <JsonConsumable>();
                foreach (Consumable food in consumables)
                {
                    if (!buffDesc.ContainsKey("b" + food.Buff.ID))
                    {
                        buffDesc["b" + food.Buff.ID] = JsonLogBuilder.BuildBuffDesc(food.Buff, log);
                    }
                    consumablesJSON.Add(JsonConsumableBuilder.BuildJsonConsumable(food));
                }
                jsonPlayer.Consumables = consumablesJSON;
            }
            //
            IReadOnlyList <DeathRecap> deathRecaps = player.GetDeathRecaps(log);

            if (deathRecaps.Any())
            {
                jsonPlayer.DeathRecap = deathRecaps.Select(x => JsonDeathRecapBuilder.BuildJsonDeathRecap(x)).ToList();
            }
            //
            jsonPlayer.DamageModifiers       = JsonDamageModifierDataBuilder.GetDamageModifiers(phases.Select(x => player.GetDamageModifierStats(null, log, x.Start, x.End)).ToList(), log, damageModDesc);
            jsonPlayer.DamageModifiersTarget = JsonDamageModifierDataBuilder.GetDamageModifiersTarget(player, log, damageModDesc, phases);
            return(jsonPlayer);
        }
        public static void FillJsonActor(JsonActor jsonActor, AbstractSingleActor actor, ParsedEvtcLog log, RawFormatSettings settings, Dictionary <string, JsonLog.SkillDesc> skillDesc, Dictionary <string, JsonLog.BuffDesc> buffDesc)
        {
            IReadOnlyList <PhaseData> phases = log.FightData.GetNonDummyPhases(log);

            //
            jsonActor.Name          = actor.Character;
            jsonActor.TotalHealth   = actor.GetHealth(log.CombatData);
            jsonActor.Toughness     = actor.Toughness;
            jsonActor.Healing       = actor.Healing;
            jsonActor.Concentration = actor.Concentration;
            jsonActor.Condition     = actor.Condition;
            jsonActor.HitboxHeight  = actor.HitboxHeight;
            jsonActor.HitboxWidth   = actor.HitboxWidth;
            jsonActor.InstanceID    = actor.AgentItem.InstID;
            jsonActor.IsFake        = actor.IsFakeActor;
            //
            jsonActor.DpsAll   = phases.Select(phase => JsonStatisticsBuilder.BuildJsonDPS(actor.GetDPSStats(log, phase.Start, phase.End))).ToArray();
            jsonActor.StatsAll = phases.Select(phase => JsonStatisticsBuilder.BuildJsonGameplayStatsAll(actor.GetGameplayStats(log, phase.Start, phase.End))).ToArray();
            jsonActor.Defenses = phases.Select(phase => JsonStatisticsBuilder.BuildJsonDefensesAll(actor.GetDefenseStats(log, phase.Start, phase.End))).ToArray();
            //
            IReadOnlyDictionary <long, Minions> minionsList = actor.GetMinions(log);

            if (minionsList.Values.Any())
            {
                jsonActor.Minions = minionsList.Values.Select(x => JsonMinionsBuilder.BuildJsonMinions(x, log, skillDesc, buffDesc)).ToList();
            }
            //
            var skillByID = actor.GetIntersectingCastEvents(log, 0, log.FightData.FightEnd).GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());

            if (skillByID.Any())
            {
                jsonActor.Rotation = JsonRotationBuilder.BuildJsonRotationList(log, skillByID, skillDesc);
            }
            //
            if (settings.RawFormatTimelineArrays)
            {
                var damage1S          = new IReadOnlyList <int> [phases.Count];
                var powerDamage1S     = new IReadOnlyList <int> [phases.Count];
                var conditionDamage1S = new IReadOnlyList <int> [phases.Count];
                var breakbarDamage1S  = new IReadOnlyList <double> [phases.Count];
                for (int i = 0; i < phases.Count; i++)
                {
                    PhaseData phase = phases[i];
                    damage1S[i]          = actor.Get1SDamageList(log, phase.Start, phase.End, null, ParserHelper.DamageType.All);
                    powerDamage1S[i]     = actor.Get1SDamageList(log, phase.Start, phase.End, null, ParserHelper.DamageType.Power);
                    conditionDamage1S[i] = actor.Get1SDamageList(log, phase.Start, phase.End, null, ParserHelper.DamageType.Condition);
                    breakbarDamage1S[i]  = actor.Get1SBreakbarDamageList(log, phase.Start, phase.End, null);
                }
                jsonActor.Damage1S          = damage1S;
                jsonActor.PowerDamage1S     = powerDamage1S;
                jsonActor.ConditionDamage1S = conditionDamage1S;
                jsonActor.BreakbarDamage1S  = breakbarDamage1S;
            }
            if (!log.CombatData.HasBreakbarDamageData)
            {
                jsonActor.BreakbarDamage1S = null;
            }
            //
            jsonActor.TotalDamageDist  = BuildDamageDistData(actor, phases, log, skillDesc, buffDesc);
            jsonActor.TotalDamageTaken = BuildDamageTakenDistData(actor, phases, log, skillDesc, buffDesc);
            //
            if (settings.RawFormatTimelineArrays)
            {
                Dictionary <long, BuffsGraphModel> buffGraphs = actor.GetBuffGraphs(log);
                jsonActor.BoonsStates      = JsonBuffsUptimeBuilder.GetBuffStates(buffGraphs[Buff.NumberOfBoonsID]);
                jsonActor.ConditionsStates = JsonBuffsUptimeBuilder.GetBuffStates(buffGraphs[Buff.NumberOfConditionsID]);
                if (buffGraphs.TryGetValue(Buff.NumberOfActiveCombatMinionsID, out BuffsGraphModel states))
                {
                    jsonActor.ActiveCombatMinions = JsonBuffsUptimeBuilder.GetBuffStates(states);
                }
                // Health
                jsonActor.HealthPercents = actor.GetHealthUpdates(log).Select(x => new double[2] {
                    x.Start, x.Value
                }).ToList();
                jsonActor.BarrierPercents = actor.GetBarrierUpdates(log).Select(x => new double[2] {
                    x.Start, x.Value
                }).ToList();
            }
            if (log.CanCombatReplay)
            {
                jsonActor.CombatReplayData = JsonActorCombatReplayDataBuilder.BuildJsonActorCombatReplayDataBuilder(actor, log, settings);
            }
        }