Beispiel #1
0
        private void ViewFight(FightInfo f)
        {
            //var s = new StringBuilder();
            //var writer = new StringWriter(s);
            //f.WriteNotes(writer);
            //LogInfo(s.ToString());

            lvPlayers.BeginUpdate();
            lvPlayers.Items.Clear();
            var top = f.Participants.Max(x => x.OutboundHitSum);

            // show participants that did damage
            foreach (var p in f.Participants.Where(x => x.OutboundHitSum > 0))
            {
                var item = lvPlayers.Items.Add(p.Name);
                item.SubItems.Add(p.Class);
                item.SubItems.Add(FightUtils.FormatNum(p.OutboundHitSum));
                item.SubItems.Add(((double)p.OutboundHitSum / top).ToString("P0"));
                item.SubItems.Add(p.Duration.ToString() + 's');
                item.SubItems.Add(FightUtils.FormatNum(p.OutboundHitSum / f.Duration));
                //var damage = String.Join(", ", p.AttackTypes.Take(4).Select(x => $"{(double)x.HitSum / p.OutboundHitSum:P0} {x.Type}"));
                var notes = String.Join(", ", p.AttackTypes.Take(4).Select(x => $"{FightUtils.FormatNum(x.HitSum / f.Duration)} {x.Type}"));
                var other = p.AttackTypes.Skip(4).Sum(x => x.HitSum);
                if (other > 0)
                {
                    notes += $", {FightUtils.FormatNum(other / f.Duration)} other";
                }
                if (p.Buffs.Any(x => x.Name == BuffTracker.DEATH))
                {
                    notes = "DIED - " + notes;
                }
                item.SubItems.Add(notes);
            }
            lvPlayers.EndUpdate();
        }
Beispiel #2
0
        private void lvFights_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            var f = GetListViewFight(e.ItemIndex);

            e.Item      = new ListViewItem();
            e.Item.Text = f.Name;
            e.Item.SubItems.Add(f.Zone);
            e.Item.SubItems.Add(f.UpdatedOn.ToLocalTime().ToString());
            e.Item.SubItems.Add(FightUtils.FormatNum(f.HP));
            e.Item.SubItems.Add(f.Duration.ToString() + "s");
            e.Item.SubItems.Add(FightUtils.FormatNum(f.HP / f.Duration));
            e.Item.SubItems.Add(f.Party + ": " + f.Participants.Count);
            fightStatus.TryGetValue(f.ID, out string status);
            e.Item.SubItems.Add(status ?? "-");
        }
Beispiel #3
0
    static void Main(string[] args)
    {
        LoadSettings();

        Application.Init();
        Colors.Base.Normal = Application.Driver.MakeAttribute(Color.Green, Color.Black);
        Colors.ColorSchemes.Add("Highlight", new ColorScheme()
        {
            Normal = Application.Driver.MakeAttribute(Color.BrightGreen, Color.Black)
        });


        var win = new Window()
        {
            X      = 0,
            Y      = 1,
            Width  = Dim.Fill(),
            Height = Dim.Fill(),
        };

        Application.Top.Add(win);
        //var win = Application.Top;

        var searchLabel = new Label()
        {
            X    = 0,
            Y    = 0,
            Text = "Search:",
        };

        win.Add(searchLabel);
        var searchField = new TextField()
        {
            X      = Pos.Right(searchLabel) + 1,
            Y      = 0,
            Width  = Dim.Sized(20),
            Height = 1,
        };

        win.Add(searchField);
        var searchCount = new Label()
        {
            X = Pos.Right(searchField) + 1,
            Y = 0,
        };

        win.Add(searchCount);

        var alwaysLabel = new Label()
        {
            X    = Pos.Right(searchCount) + 3,
            Y    = 0,
            Text = "Always Show:",
        };

        win.Add(alwaysLabel);
        var alwaysField = new TextField()
        {
            X       = Pos.Right(alwaysLabel) + 1,
            Y       = 0,
            Width   = Dim.Sized(20),
            Height  = 1,
            TabStop = false,
        };

        win.Add(alwaysField);

        var modeLabel = new Label()
        {
            X    = Pos.Right(alwaysField) + 3,
            Y    = 0,
            Text = "Mode:",
        };

        win.Add(modeLabel);
        var modeRadio = new RadioGroup()
        {
            X               = Pos.Right(modeLabel) + 1,
            Y               = 0,
            Width           = Dim.Sized(20),
            RadioLabels     = new NStack.ustring[] { "Total  ", "DPS  ", "%Total  " },
            HorizontalSpace = 2,
            DisplayMode     = DisplayModeLayout.Horizontal,
            TabStop         = false, // annoying when tabbing between search and fights
            SelectedItem    = settings.Mode,
        };

        win.Add(modeRadio);

        //var fightSource = new FightDataSource(fightList);
        //var fightView = new ListView(fightSource)
        var fightView = new ListView(fightList)
        {
            X      = 0,
            Y      = 2,
            Width  = Dim.Fill(),
            Height = Dim.Percent(50),
            //Height = 18,
        };

        win.Add(fightView);

        // the bottom portion of the screen will contain "slots" for individual player information
        var slots = new List <View>();

        for (var i = 0; i < 6; i++)
        {
            var slotView = new FrameView()
            {
                X      = 0 + (i * 25),
                Y      = Pos.Bottom(fightView) + 1,
                Width  = 25,
                Height = Dim.Fill(),
            };
            var slotText = new Label()
            {
                X      = 0,
                Y      = 0,
                Height = 10,
                Width  = Dim.Fill(),
                Text   = "..."
            };
            slotView.Add(slotText);
            win.Add(slotView);
            slots.Add(slotText);
        }

        var status = new StatusBar()
        {
            Visible = true,
            Items   = new StatusItem[] {
                new StatusItem(Key.Null, "...", () => { }),
                new StatusItem(Key.Null, "...", () => { }),
                new StatusItem(Key.Null, "Alt+Enter to toggle full screen", () => { })
            },
            Text = "Ready..."
        };

        Application.Top.Add(status);

        searchField.KeyDown += (key) =>
        {
            if (key.KeyEvent.Key == Key.Esc)
            {
                searchField.Text = "";
            }
        };

        searchField.TextChanged += (_) =>
        {
            var s = searchField.Text.ToString();
            if (String.IsNullOrEmpty(s))
            {
                fightListSource = null;
                fightView.SetSource(fightList);
                searchCount.Text = "";
            }
            else
            {
                fightListSource = fightList.Where(x => x.IsMatch(s)).ToList();
                fightView.SetSource(fightListSource);
                fightView.OnSelectedChanged();
                searchCount.Text = $"{fightListSource.Count} matches";
            }
        };

        alwaysField.TextChanged += (_) =>
        {
            fightView.OnSelectedChanged();
        };

        modeRadio.SelectedItemChanged += (args) =>
        {
            fightView.OnSelectedChanged();
        };

        fightView.SelectedItemChanged += (args) =>
        {
            var list = fightListSource ?? fightList;

            if (args.Item >= list.Count)
            {
                return;
            }

            var f = list[args.Item].Info;
            //status.Items[2].Title = DateTime.Now.ToString() + " " + f.Name + " " + f.Participants[0].OutboundHitSum;

            var mode = modeRadio.SelectedItem;

            var players = f.Participants.Take(slots.Count).ToList();

            var always = alwaysField.Text.ToString().Split(',', StringSplitOptions.RemoveEmptyEntries);
            if (always.Length > 0)
            {
                players = f.Participants
                          .Select((x, i) => new { Always = always.Contains(x.Name, StringComparer.InvariantCultureIgnoreCase) && x.OutboundHitSum > 0, Index = i, Player = x })
                          .OrderBy(x => !x.Always).ThenBy(x => x.Index)
                          .Take(slots.Count)
                          .OrderBy(x => x.Index) // restore order after take() keeps the "always" entries
                          .Select(x => x.Player)
                          .ToList();
            }

            for (var i = 0; i < slots.Count; i++)
            {
                slots[i].Text = "";

                if (i >= players.Count)
                {
                    continue;
                }

                var p = players[i];
                if (p.OutboundHitSum == 0)
                {
                    continue;
                }

                var text = new StringBuilder();
                text.AppendLine($"{p.Name} - {p.Class}");
                if (mode == 0)
                {
                    text.AppendLine($"{FightUtils.FormatNum(p.OutboundHitSum)}");
                }
                else if (mode == 1)
                {
                    text.AppendLine($"{FightUtils.FormatNum(p.OutboundHitSum / f.Duration)} DPS");
                }
                else if (mode == 2)
                {
                    text.AppendLine($"{((double)p.OutboundHitSum / f.HP).ToString("P1")} of Total");
                    text.AppendLine($"{((double)p.OutboundHitSum / f.TopHitSum).ToString("P1")} vs Top Player");
                }
                text.AppendLine("---");
                foreach (var dmg in p.AttackTypes)
                {
                    if (mode == 0)
                    {
                        text.AppendLine($"{Clip(dmg.Type, 15),-15} {FightUtils.FormatNum(dmg.HitSum),6}");
                    }
                    else if (mode == 1)
                    {
                        text.AppendLine($"{Clip(dmg.Type, 15),-15} {FightUtils.FormatNum(dmg.HitSum / f.Duration),6}");
                    }
                    else if (mode == 2)
                    {
                        text.AppendLine($"{Clip(dmg.Type, 15),-15} {((double)dmg.HitSum / p.OutboundHitSum).ToString("P0"),6}");
                    }
                }
                text.AppendLine("---");
                foreach (var spell in p.Spells.Where(x => x.HitSum > 0 && x.Type == "hit"))
                {
                    if (mode == 0)
                    {
                        text.AppendLine($"{Clip(spell.Name, 15),-15} {FightUtils.FormatNum(spell.HitSum),6}");
                    }
                    else if (mode == 1)
                    {
                        text.AppendLine($"{Clip(spell.Name, 15),-15} {FightUtils.FormatNum(spell.HitSum / f.Duration),6}");
                    }
                    else if (mode == 2)
                    {
                        text.AppendLine($"{Clip(spell.Name, 15),-15} {((double)spell.HitSum / p.OutboundHitSum).ToString("P0"),6}");
                    }
                }
                slots[i].Text = text.ToString();
                slots[i].SuperView.ColorScheme = always.Contains(p.Name, StringComparer.InvariantCultureIgnoreCase) ? Colors.ColorSchemes["Highlight"] : Colors.Base;
            }
        };

        var path = settings.Path;

        if (args.Length > 1 && File.Exists(args[1]))
        {
            path = args[1];
        }
        if (File.Exists(path))
        {
            alwaysField.Text      = LogOpenEvent.FromFileName(path)?.Player ?? "";
            status.Items[2].Title = path;
            _ = OpenLog(path);
            //status.Items[2].Title = "";
        }

        Func <Exception, bool> errorHandler = (Exception e) =>
        {
            MessageBox.ErrorQuery("Error", e.Message + "\n", "OK");
            return(true);
        };

        var menu = new MenuBar(new MenuBarItem[] {
            new MenuBarItem("_File", new MenuItem [] {
                new MenuItem("_Open", "", () => {
                    var open = new OpenDialog();
                    open.AllowedFileTypes        = new[] { ".txt" };
                    open.Message                 = "Select a file starting with: eqlog_";
                    open.LayoutStyle             = LayoutStyle.Computed;
                    open.AllowsMultipleSelection = false;
                    if (File.Exists(settings.Path))
                    {
                        open.DirectoryPath = Path.GetDirectoryName(settings.Path);
                    }
                    Application.Run(open);
                    if (!open.Canceled)
                    {
                        fightView.SelectedItem = 0;
                        path                  = open.FilePath.ToString();
                        alwaysField.Text      = LogOpenEvent.FromFileName(path)?.Player ?? "";
                        status.Items[2].Title = path;
                        _ = OpenLog(path);
                    }
                }),
                new MenuItem("_Quit", "", () => {
                    Application.RequestStop();
                })
            }),
        });

        Application.Top.Add(menu);

        Application.MainLoop.AddTimeout(TimeSpan.FromMilliseconds(100), (_) =>
        {
            var count = 0;
            while (fightQueue.TryDequeue(out FightInfo f) && count++ < 50)
            {
                //fightList.Add(f); // oldest to newest
                fightList.Insert(0, new FightInfoRow(f)); // newest to oldest
            }
            if (count > 0)
            {
                status.Items[0].Title = $"{fightList.Count} fights";
                fightView.OnSelectedChanged();
                //status.SetNeedsDisplay();
                //fightView.SetNeedsDisplay();
                if (logReader != null)
                {
                    status.Items[1].Title = $"{logReader.Percent:P0} in {logReader.Elapsed:F1}s";
                }
            }
            return(true);
        });