Esempio n. 1
0
        public override void Merge(FightInfo f)
        {
            // add to internal list and delay actual merge until the Finish is called
            fights.Add(f);

            // raid needs a timestamp to keep from getting timed out
            if (StartedOn == DateTime.MinValue || StartedOn > f.StartedOn)
            {
                StartedOn = f.StartedOn;
            }
        }
Esempio n. 2
0
        private void TrackHit(LogHitEvent hit)
        {
            var foe = Chars.GetFoe(hit.Source, hit.Target);

            if (foe == null)
            {
                //Console.WriteLine("*** " + hit);
                if (hit.Source != hit.Target)
                {
                    PendingHits.Add(hit);
                }
                return;
            }

            if (hit.Source.EndsWith("'s corpse"))
            {
                if (hit.Target == foe)
                {
                    // rename source to track damage from dead player
                    hit = new LogHitEvent
                    {
                        Timestamp = hit.Timestamp,
                        Type      = hit.Type,
                        Source    = hit.Source.Substring(0, hit.Source.Length - 9),
                        Target    = hit.Target,
                        Amount    = hit.Amount,
                        Mod       = hit.Mod,
                        Spell     = hit.Spell
                    };
                }
                else
                {
                    // do not track damage from a dead mob
                    return;
                }
            }

            var f = GetOrAddFight(foe);

            if (f == null)
            {
                return;
            }

            f.AddHit(hit);
            //LastHit = hit;
            LastFight = f;
        }
Esempio n. 3
0
        private void TrackMiss(LogMissEvent miss)
        {
            var foe = Chars.GetFoe(miss.Source, miss.Target);

            if (foe == null)
            {
                return;
            }

            var f = GetOrAddFight(foe);

            if (f == null)
            {
                return;
            }

            f.AddMiss(miss);
            LastFight = f;
        }
Esempio n. 4
0
        /// <summary>
        /// Output a short summary of each players damage to a TextWriter.
        /// </summary>
        public static void WriteShortSummary(this TextWriter writer, FightInfo fight)
        {
            writer.WriteLine();
            writer.WriteLine("** {0} ** {1} HP in {2}s at {3}", fight.Name, FormatNum(fight.Target.InboundHitSum), fight.Duration, fight.StartedOn.ToLocalTime().ToShortTimeString(), fight.Zone);
            if (fight.Participants.Count == 0)
            {
                return;
            }

            var top = fight.Participants.Max(x => x.OutboundHitSum);

            foreach (var p in fight.Participants.Take(10).Where(x => x.OutboundHitSum > 0))
            {
                // percent = share of damage vs mob
                //var pct = (float)p.OutboundHitSum / Target.InboundHitSum;
                // percent = damage relative to top player
                var pct = (float)p.OutboundHitSum / top;
                writer.WriteLine(" {0,-20} --- {1,4:P0} {2,8} / {3,5} DPS", p, pct, FormatNum(p.OutboundHitSum), FormatNum(p.OutboundHitSum / fight.Duration));
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Output a detailed summary of each players damage, tanking, and spells to a TextWriter.
        /// </summary>
        public static void WriteLongSummary(this TextWriter writer, FightInfo fight)
        {
            writer.WriteLine();
            writer.WriteLine("**{0}** {1:N0} HP in {2}s at {3}", fight.Name, fight.Target.InboundHitSum, fight.Duration, fight.StartedOn.ToLocalTime(), fight.Zone);
            if (fight.Participants.Count == 0)
            {
                return;
            }

            var top = fight.Participants.Max(x => x.OutboundHitSum);

            foreach (var p in fight.Participants)
            {
                var pct = (float)p.OutboundHitSum / top;

                writer.WriteLine(" {0} {1:P0} {2} to {3}", p, pct, p.FirstAction?.ToLocalTime().ToString("T"), p.LastAction?.ToLocalTime().ToString("T"));

                writer.WriteLine("   {0,-10} {1,11:N0} / {2,6:N0} DPS", "total", p.OutboundHitSum, p.OutboundHitSum / fight.Duration);
                foreach (var ht in p.AttackTypes)
                {
                    writer.WriteLine("   {0,-10} {1,11:N0} / {2,6:N0} DPS", ht.Type, ht.HitSum, ht.HitSum / fight.Duration);
                }

                foreach (var d in p.DefenseTypes)
                {
                    writer.WriteLine("   {0,-10} {1,6:N0} of {2} {3:P0}", "*" + d.Type + "*", d.Count, d.Attempts, (double)d.Count / d.Attempts);
                }

                writer.WriteLine("   {0,-10} {1,6:N0} of {2} {3:P0}", "*hit*", p.InboundHitCount, p.InboundHitCount + p.InboundMissCount, (double)p.InboundHitCount / (p.InboundHitCount + p.InboundMissCount));

                foreach (var s in p.Spells)
                {
                    writer.WriteLine("   spell {0} {1}: {2:N0}", s.Type, s.Name, s.HitSum);
                }

                foreach (var h in p.Heals)
                {
                    writer.WriteLine("   healed {0}: {1:N0}", h.Target, h.HitSum);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Merge data from another fight into this fight.
        /// The supplied fight must have started after any previously merged fights.
        /// </summary>
        public virtual void Merge(FightInfo f)
        {
            if (Target == null || String.IsNullOrEmpty(Target.Name))
            {
                Target = new FightParticipant()
                {
                    Name = "X"
                };
                Name      = "X";
                Zone      = f.Zone;
                Party     = f.Party;
                Player    = f.Player;
                Server    = f.Server;
                StartedOn = f.StartedOn;
                UpdatedOn = f.UpdatedOn;
                Status    = FightStatus.Merged;
                Duration  = 1;
            }

            MobCount += 1;
            fights.Add(f);

            if (Zone != f.Zone)
            {
                Zone = "Multiple Zones";
            }

            if (Party == "Group" && f.Party == "Raid")
            {
                Party = "Raid";
            }

            //Target.Merge(f.Target, 0);

            if (StartedOn > f.StartedOn && intervals.Count == 1)
            {
                StartedOn = f.StartedOn;
            }
            else if (StartedOn > f.StartedOn)
            {
                throw new Exception("Fights must be merged in order of start time.");
            }

            if (UpdatedOn < f.UpdatedOn)
            {
                UpdatedOn = f.UpdatedOn;
            }


            /*
             * for single fights each tick has a 1 to 1 mapping to intervals.
             * however when merging multiple fights together we have to deal with
             * ticks that may overlap intervals (which we need to merge) and
             * gaps between fights (which we want to remove).
             *
             * here are some scenarios that will occur:
             *
             *         1111
             * 12345678  90123   -- intervals we want to assign
             * ---------------   -- the tick timeline
             * 1111              -- first fight
             * 22222          -- 2nd overlaps with 1st
             *        33333   -- 3rd has gap after 2nd
             *         44     -- 4th ends before 3rd
             *
             * fights must be sorted in starting order for this algorithm to work
             */

            // starting interval
            var interval = 0;
            // get tick relative to first tick of first fight
            var head = GetTick(f.StartedOn);
            var tail = GetTick(f.UpdatedOn);

            Debug.Assert(tail >= head);

            // has this tick already been seen?
            // if so backtrack so we can find where it belongs
            if (head <= intervals[^ 1])
            {
                interval = intervals.Count - 1;
                while (intervals[interval] > head)
                {
                    interval--;
                }
            }
            // if it hasn't been seen then add it as a new interval
            else
            {
                intervals.Add(head);
                interval = intervals.Count - 1;
            }

            // handle the tail
            var current = intervals[^ 1];