예제 #1
0
        private static ExcelWorksheet CreateDetailsSheet(ExcelPackage package, ExtendedStats exdata)
        {
            var timeFormat = (exdata.LastTick - exdata.FirstTick) / TimeSpan.TicksPerSecond < 40 ? "ss" : "mm:ss";
            var details    = package.Workbook.Worksheets.Add("Details");

            details.Cells[1, 1].Value = "Boss";
            details.Cells[2, 1].Value = "Seconds";
            details.Cells[2, 2].Value = "Time";
            details.Column(2).Style.Numberformat.Format = timeFormat;
            details.Cells[2, 3].Value = "BuffNum";
            details.Cells[2, 4].Value = "Start";
            details.Column(4).Style.Numberformat.Format = timeFormat;
            details.Cells[2, 5].Value = "Duration";
            details.Column(5).Style.Numberformat.Format = timeFormat;
            details.Cells[2, 6].Value = "BuffName";
            details.Cells[2, 7].Value = "Axis";
            details.Cells[2, 8].Value = "Damage";
            details.Column(8).Style.Numberformat.Format = @"#,#0\k";
            details.Cells[2, 9].Value = "AvgDPS";
            details.Column(9).Style.Numberformat.Format = @"#,#0\k\/\s";
            details.Cells[2, 10].Value = "BossHP";
            details.Column(10).Style.Numberformat.Format = "0%";
            details.Cells[1, 1, 1, 10].Merge             = true;

            for (int t = 0; t <= exdata.LastTick / TimeSpan.TicksPerSecond - exdata.FirstTick / TimeSpan.TicksPerSecond; t++)
            {
                details.Cells[t + 3, 1].Value = t;
                details.Cells[t + 3, 2].Value = (double)t / 86400;
            }
            var buffnum = 0;
            var j       = 0;

            foreach (var buffPair in exdata.Debuffs)
            {
                if (buffPair.Value.Count() == 0)
                {
                    continue;
                }
                buffnum++;
                details.Cells[2 + buffnum, 6].Value = buffPair.Key.Name;
                details.Cells[2 + buffnum, 7].Value = 0;
                foreach (var buff in buffPair.Value.AllDurations())
                {
                    j++;
                    details.Cells[2 + j, 3].Value = buffnum;
                    details.Cells[2 + j, 4].Value = (double)(buff.Begin - exdata.FirstTick) / TimeSpan.TicksPerDay;
                    details.Cells[2 + j, 5].Value = (double)(buff.End - buff.Begin) / TimeSpan.TicksPerDay;
                }
            }
            long dealtDamage = 0;
            var  totalDamage = exdata.PlayerSkills.Sum(
                x => x.Value.Where(time => time.Time >= exdata.FirstTick && time.Time <= exdata.LastTick)
                .Sum(y => y.Amount));

            j = 0;
            for (var curTick = exdata.FirstTick;
                 curTick <= exdata.LastTick;
                 curTick += TimeSpan.TicksPerSecond)
            {
                j++;
                var damage =
                    exdata.PlayerSkills.Sum(
                        x => x.Value.Where(time => time.Time >= curTick && time.Time <= curTick + TimeSpan.TicksPerSecond)
                        .Sum(skill => skill.Amount));
                dealtDamage += damage;
                details.Cells[j + 2, 8].Value = damage / 1000;
                if (curTick >= exdata.LastTick + TimeSpan.TicksPerSecond)
                {
                    details.Cells[j + 2, 9].Value = dealtDamage * TimeSpan.TicksPerSecond /
                                                    (exdata.LastTick - exdata.FirstTick) / 1000;
                }
                else if (j != 1)
                {
                    details.Cells[j + 2, 9].Value = dealtDamage / (j - 1) / 1000;
                }
                details.Cells[j + 2, 10].Value = totalDamage == 0 ? 0 : (double)(totalDamage - dealtDamage) / totalDamage;
            }
            var i = 4;

            foreach (var user in exdata.PlayerBuffs)
            {
                i += 7;
                details.Cells[1, i].Value     = user.Key;
                details.Cells[2, i].Value     = "BuffNum";
                details.Cells[2, i + 1].Value = "Start";
                details.Column(i + 1).Style.Numberformat.Format = timeFormat;
                details.Cells[2, i + 2].Value = "Duration";
                details.Column(i + 2).Style.Numberformat.Format = timeFormat;
                details.Cells[2, i + 3].Value = "BuffName";
                details.Cells[2, i + 4].Value = "Axis";
                details.Cells[2, i + 5].Value = "Damage";
                details.Column(i + 5).Style.Numberformat.Format = @"#,#0\k";
                details.Cells[2, i + 6].Value = "AvgDPS";
                details.Column(i + 6).Style.Numberformat.Format = @"#,#0\k\/\s";
                details.Cells[1, i, 1, i + 6].Merge             = true;
                buffnum = 0;
                j       = 0;
                foreach (var buffPair in user.Value.Times)
                {
                    if (buffPair.Value.Count() == 0)
                    {
                        continue;
                    }
                    buffnum++;
                    details.Cells[2 + buffnum, i + 3].Value = buffPair.Key.Name;
                    details.Cells[2 + buffnum, i + 4].Value = 0;
                    foreach (var buff in buffPair.Value.AllDurations())
                    {
                        j++;
                        details.Cells[2 + j, i].Value     = buffnum;
                        details.Cells[2 + j, i + 1].Value = (double)(buff.Begin - exdata.FirstTick) /
                                                            TimeSpan.TicksPerDay;
                        details.Cells[2 + j, i + 2].Value = (double)(buff.End - buff.Begin) / TimeSpan.TicksPerDay;
                    }
                }
                if (user.Value.Death.Count() > 0)
                {
                    buffnum++;
                    details.Cells[2 + buffnum, i + 3].Value = LP.Deaths;
                    details.Cells[2 + buffnum, i + 4].Value = 0;
                    foreach (var buff in user.Value.Death.AllDurations())
                    {
                        j++;
                        details.Cells[2 + j, i].Value     = buffnum;
                        details.Cells[2 + j, i + 1].Value = (double)(buff.Begin - exdata.FirstTick) /
                                                            TimeSpan.TicksPerDay;
                        details.Cells[2 + j, i + 2].Value = (double)(buff.End - buff.Begin) / TimeSpan.TicksPerDay;
                    }
                }
                if (user.Value.Aggro(exdata.Entity).Count() > 0)
                {
                    buffnum++;
                    details.Cells[2 + buffnum, i + 3].Value = LP.Aggro;
                    details.Cells[2 + buffnum, i + 4].Value = 0;
                    foreach (var buff in user.Value.Aggro(exdata.Entity).AllDurations())
                    {
                        j++;
                        details.Cells[2 + j, i].Value     = buffnum;
                        details.Cells[2 + j, i + 1].Value = (double)(buff.Begin - exdata.FirstTick) /
                                                            TimeSpan.TicksPerDay;
                        details.Cells[2 + j, i + 2].Value = (double)(buff.End - buff.Begin) / TimeSpan.TicksPerDay;
                    }
                }
                dealtDamage = 0;
                j           = 0;
                for (var curTick = exdata.FirstTick;
                     curTick <= exdata.LastTick;
                     curTick += TimeSpan.TicksPerSecond)
                {
                    j++;
                    var damage =
                        exdata.PlayerSkills.Where(all => all.Key == user.Key).Sum(
                            x => x.Value.Where(time => time.Time >= curTick && time.Time <= curTick + TimeSpan.TicksPerSecond)
                            .Sum(skill => skill.Amount));
                    dealtDamage += damage;
                    details.Cells[j + 2, i + 5].Value = damage / 1000;
                    if (curTick >= exdata.LastTick + TimeSpan.TicksPerSecond)
                    {
                        details.Cells[j + 2, i + 6].Value = dealtDamage * TimeSpan.TicksPerSecond /
                                                            (exdata.LastTick - exdata.FirstTick) / 1000;
                    }
                    else if (j != 1)
                    {
                        details.Cells[j + 2, i + 6].Value = dealtDamage / (j - 1) / 1000;
                    }
                }
            }

            return(details);
        }
예제 #2
0
        private static ExcelHyperLink CreateUserSheet(ExcelWorkbook wb, Members user, ExtendedStats exdata,
                                                      ExcelWorksheet details)
        {
            var ws  = wb.Worksheets.Add($"{user.playerServer}_{user.playerName}");
            var rgc = new RaceGenderClass("Common", "Common", user.playerClass);

            ws.DefaultRowHeight      = 30;
            ws.Cells.Style.Font.Size = 14;
            ws.Cells.Style.Font.Name = "Arial";
            AddImage(ws, 1, 1,
                     ClassIcons.Instance.GetBitmap((PlayerClass)Enum.Parse(typeof(PlayerClass), user.playerClass)));
            ws.Cells[1, 2].Value                  = $"{user.playerServer}: {user.playerName}";
            ws.Cells[1, 2, 1, 11].Merge           = true;
            ws.Cells[1, 2, 1, 11].Style.Font.Bold = true;
            ws.Cells[2, 2].Value                  = LP.SkillName;
            ws.Cells[2, 3].Value                  = LP.DamagePercent;
            ws.Cells[2, 4].Value                  = LP.Damage;
            ws.Cells[2, 5].Value                  = LP.CritPercent;
            ws.Cells[2, 6].Value                  = LP.Hits;
            ws.Cells[2, 7].Value                  = LP.Crits;
            ws.Cells[2, 8].Value                  = LP.MaxCrit;
            ws.Cells[2, 9].Value                  = LP.MinCrit;
            ws.Cells[2, 10].Value                 = LP.AverageCrit;
            ws.Cells[2, 11].Value                 = LP.AvgWhite;
            var i = 2;

            foreach (var stat in exdata.PlayerSkillsAggregated[user.playerServer + "/" + user.playerName].OrderByDescending(x => x.Amount()))
            {
                i++;
                ws.Cells[i, 1].Value = i - 2;
                foreach (var skillInfo in stat.Skills)
                {
                    if (string.IsNullOrEmpty(skillInfo.Key.IconName))
                    {
                        continue;
                    }
                    AddImage(ws, i, 1, BTD.Icons.GetBitmap(skillInfo.Key.IconName));
                    break;
                }

                ws.Cells[i, 2].Value = stat.Name;
                ws.Cells[i, 3].Value = stat.DamagePercent() / 100;
                ws.Cells[i, 3].Style.Numberformat.Format = "0.0%";
                ws.Cells[i, 4].Value = stat.Amount();
                ws.Cells[i, 4].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 5].Value = stat.CritRate() / 100;
                ws.Cells[i, 5].Style.Numberformat.Format = "0.0%";
                ws.Cells[i, 6].Value = stat.Hits();
                ws.Cells[i, 7].Value = stat.Crits();
                ws.Cells[i, 8].Value = stat.BiggestCrit();
                ws.Cells[i, 8].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 9].Value = stat.LowestCrit();
                ws.Cells[i, 9].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 10].Value = stat.AvgCrit();
                ws.Cells[i, 10].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 11].Value = stat.AvgWhite();
                ws.Cells[i, 11].Style.Numberformat.Format = @"#,#0,\k";
            }
            var border = ws.Cells[1, 1, i, 11].Style.Border;

            border.Bottom.Style = border.Top.Style = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;
            ws.Cells[2, 1, i, 11].AutoFilter = true;

            var j = i + 3;

            ws.Cells[j, 2].Value                  = LP.Name;
            ws.Cells[j, 2, j, 10].Merge           = true;
            ws.Cells[j, 11].Value                 = "%";
            ws.Cells[j, 2, j, 11].Style.Font.Bold = true;
            foreach (var buf in user.buffUptime)
            {
                j++;
                var hotdot = BTD.HotDotDatabase.Get(int.Parse(buf.Key));
                ws.Cells[j, 1].Value = j - i - 3;
                AddImage(ws, j, 1, BTD.Icons.GetBitmap(hotdot.IconName));
                ws.Cells[j, 2].Value = hotdot.Name;
                if (!string.IsNullOrEmpty(hotdot.Tooltip))
                {
                    ws.Cells[j, 2].AddComment("" + hotdot.Tooltip, "info");
                }
                ws.Cells[j, 2, j, 10].Merge = true;
                ws.Cells[j, 11].Value       = double.Parse(buf.Value) / 100;
                ws.Cells[j, 11].Style.Numberformat.Format = "0%";
                if (!string.IsNullOrEmpty(hotdot.ItemName))
                {
                    ws.Cells[j, 10].AddComment("" + hotdot.ItemName, "info");
                }
            }
            border = ws.Cells[i + 3, 1, j, 11].Style.Border;
            border.Bottom.Style = border.Top.Style = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;

            AddCharts(ws, exdata, details, j);

            ws.Column(1).Width = 5.6;
            ws.Column(2).AutoFit();
            ws.Column(3).AutoFit();
            ws.Column(4).AutoFit();
            ws.Column(5).AutoFit();
            ws.Column(6).AutoFit();
            ws.Column(7).AutoFit();
            ws.Column(8).AutoFit();
            ws.Column(9).AutoFit();
            ws.Column(10).AutoFit();
            ws.Column(11).AutoFit();
            ws.Column(2).Width  = GetTrueColumnWidth(ws.Column(2).Width);
            ws.Column(3).Width  = GetTrueColumnWidth(ws.Column(3).Width);
            ws.Column(4).Width  = GetTrueColumnWidth(ws.Column(4).Width);
            ws.Column(5).Width  = GetTrueColumnWidth(ws.Column(5).Width);
            ws.Column(6).Width  = GetTrueColumnWidth(ws.Column(6).Width);
            ws.Column(7).Width  = GetTrueColumnWidth(ws.Column(7).Width);
            ws.Column(8).Width  = GetTrueColumnWidth(ws.Column(8).Width);
            ws.Column(9).Width  = GetTrueColumnWidth(ws.Column(9).Width);
            ws.Column(10).Width = GetTrueColumnWidth(ws.Column(10).Width);
            ws.Column(11).Width = GetTrueColumnWidth(ws.Column(11).Width);
            ws.Cells[1, 1, j, 11].Style.VerticalAlignment   = ExcelVerticalAlignment.Center;
            ws.Cells[1, 1, j, 11].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
            ws.PrinterSettings.FitToPage = true;

            // I don't know why, but sometimes column height setting is lost.
            for (var x = 1; x < j; ++x)
            {
                ws.Row(x).CustomHeight = true;
                ws.Row(x).Height       = 30;
            }

            // If sheet name contains space character, name should be enclosed in single quotes.
            return(new ExcelHyperLink($"'{user.playerServer}_{user.playerName}'!A1",
                                      $"{user.playerServer}: {user.playerName}"));
        }
예제 #3
0
        public static void ExcelSave(ExtendedStats exdata, string userName = "")
        {
            lock (savelock) //can't save 2 excel files at one time
            {
                if (!BTD.WindowData.Excel)
                {
                    return;
                }
                var data = exdata.BaseStats;
                var Boss = exdata.Entity.Info;

                /*
                 * Select save directory
                 */
                string dir;
                if (BTD.WindowData.ExcelSaveDirectory == "")
                {
                    if (BTD.WindowData.DateInExcelPath)
                    {
                        dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                           $"ShinraMeter/{Boss.Area.Replace(":", "-")}/{DateTime.Now.ToString("yyyy-MM-dd")}");
                    }
                    else
                    {
                        dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                           $"ShinraMeter/{Boss.Area.Replace(":", "-")}");
                    }
                }
                else
                {
                    if (BTD.WindowData.DateInExcelPath)
                    {
                        dir = $"{BTD.WindowData.ExcelSaveDirectory}/{Boss.Area.Replace(":", "-")}/{DateTime.Now.ToString("yyyy-MM-dd")}";
                    }
                    else
                    {
                        dir = $"{BTD.WindowData.ExcelSaveDirectory}/{Boss.Area.Replace(":", "-")}";
                    }
                    dir = BTD.WindowData.ExcelSaveDirectory;
                }

                /*
                 * Test if you have access to the user choice directory, if not, switch back to the default save directory
                 */
                try
                {
                    Directory.CreateDirectory(dir);
                }
                catch
                {
                    if (BTD.WindowData.DateInExcelPath)
                    {
                        dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                           $"ShinraMeter/{Boss.Area.Replace(":", "-")}/{DateTime.Now.ToString("yyyy-MM-dd")}");
                    }
                    else
                    {
                        dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                           $"ShinraMeter/{Boss.Area.Replace(":", "-")}");
                    }
                    Directory.CreateDirectory(dir);
                }
                var fname = "";
                if (BTD.WindowData.DateInExcelPath)
                {
                    fname = Path.Combine(dir,
                                         $"{Boss.Name.Replace(":", "-")} {DateTime.Now.ToString("HH-mm-ss", CultureInfo.InvariantCulture)} {userName}.xlsx");
                }
                else
                {
                    fname = Path.Combine(dir,
                                         $"{Boss.Name.Replace(":", "-")} {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture)} {userName}.xlsx");
                }
                var file = new FileInfo(fname);
                if (file.Exists)
                {
                    return;
                }
                //the only case this can happen is BAM mobtraining, that's not so interesting statistic to deal with more complex file names.
                using (var package = new ExcelPackage(file))
                {
                    var details   = CreateDetailsSheet(package, exdata);
                    var ws        = package.Workbook.Worksheets.Add(LP.Boss);
                    var linkStyle = package.Workbook.Styles.CreateNamedStyle("HyperLink");
                    //This one is language dependent
                    linkStyle.Style.Font.UnderLine = true;
                    linkStyle.Style.Font.Color.SetColor(Color.Blue);
                    ws.DefaultRowHeight      = 30;
                    ws.Cells.Style.Font.Size = 14;
                    ws.Cells.Style.Font.Name = "Arial";
                    ws.Cells[1, 1].Value     =
                        $"{Boss.Area}: {Boss.Name} {TimeSpan.FromSeconds(double.Parse(data.fightDuration)).ToString(@"mm\:ss")}";
                    ws.Cells[1, 1, 1, 9].Merge            = true;
                    ws.Cells[1, 1, 1, 11].Style.Font.Bold = true;
                    ws.Cells[1, 10].Value = long.Parse(data.partyDps);
                    ws.Cells[1, 10].Style.Numberformat.Format = @"#,#00,\k\/\s";
                    ws.Cells[2, 1].Value = "Ic";
                    ws.Cells[2, 1].Style.Font.Color.SetColor(Color.Transparent);
                    ws.Cells[2, 2].Value  = LP.Name;
                    ws.Cells[2, 3].Value  = LP.Deaths;
                    ws.Cells[2, 4].Value  = LP.Death_Time;
                    ws.Cells[2, 5].Value  = LP.DamagePercent;
                    ws.Cells[2, 6].Value  = LP.CritPercent;
                    ws.Cells[2, 7].Value  = LP.HealCritPercent;
                    ws.Cells[2, 8].Value  = LP.HitsTaken;
                    ws.Cells[2, 9].Value  = LP.DamgeTaken;
                    ws.Cells[2, 10].Value = LP.Dps;
                    ws.Cells[2, 11].Value = LP.Damage;
                    var i = 2;
                    foreach (var user in data.members.OrderByDescending(x => long.Parse(x.playerTotalDamage)))
                    {
                        i++;
                        ws.Cells[i, 1].Value = i - 2;
                        AddImage(ws, i, 1,
                                 ClassIcons.Instance.GetBitmap(
                                     (PlayerClass)Enum.Parse(typeof(PlayerClass), user.playerClass)));
                        ws.Cells[i, 2].Value     = $"{user.playerServer}: {user.playerName}";
                        ws.Cells[i, 2].Hyperlink = CreateUserSheet(package.Workbook, user, exdata, details);
                        ws.Cells[i, 3].Value     = long.Parse(user.playerDeaths);
                        ws.Cells[i, 4].Value     = long.Parse(user.playerDeathDuration);
                        ws.Cells[i, 4].Style.Numberformat.Format = @"0\s";
                        ws.Cells[i, 5].Value = double.Parse(user.playerTotalDamagePercentage) / 100;
                        ws.Cells[i, 5].Style.Numberformat.Format = "0.0%";
                        ws.Cells[i, 6].Value = double.Parse(user.playerAverageCritRate) / 100;
                        ws.Cells[i, 6].Style.Numberformat.Format = "0.0%";
                        ws.Cells[i, 7].Value = string.IsNullOrEmpty(user.healCrit) ? 0 : double.Parse(user.healCrit) / 100;
                        ws.Cells[i, 7].Style.Numberformat.Format = "0.0%";
                        ws.Cells[i, 8].Value = exdata.PlayerReceived[user.playerName].Item1;
                        ws.Cells[i, 9].Value = exdata.PlayerReceived[user.playerName].Item2;
                        ws.Cells[i, 9].Style.Numberformat.Format = @"#,#0,\k";
                        ws.Cells[i, 10].Value = long.Parse(user.playerDps);
                        ws.Cells[i, 10].Style.Numberformat.Format = @"#,#0,\k\/\s";
                        ws.Cells[i, 11].Value = long.Parse(user.playerTotalDamage);
                        ws.Cells[i, 11].Style.Numberformat.Format = @"#,#0,\k";
                    }
                    ws.Cells[1, 11].Formula = $"SUM(K3:K{i})";
                    ws.Cells[1, 11].Style.Numberformat.Format = @"#,#0,\k";
                    var border = ws.Cells[1, 1, i, 11].Style.Border;
                    border.Bottom.Style              =
                        border.Top.Style             = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;
                    ws.Cells[2, 1, i, 11].AutoFilter = true;

                    var j = i + 3;
                    ws.Cells[j, 1].Value = "Ic";
                    ws.Cells[j, 1].Style.Font.Color.SetColor(Color.Transparent);
                    ws.Cells[j, 2].Value                  = LP.Name;
                    ws.Cells[j, 2, j, 10].Merge           = true;
                    ws.Cells[j, 11].Value                 = "%";
                    ws.Cells[j, 2, j, 11].Style.Font.Bold = true;
                    foreach (var buf in data.debuffUptime)
                    {
                        j++;
                        var hotdot = BTD.HotDotDatabase.Get(int.Parse(buf.Key));
                        ws.Cells[j, 1].Value = j - i - 3;
                        AddImage(ws, j, 1, BTD.Icons.GetBitmap(hotdot.IconName));
                        ws.Cells[j, 2].Value = hotdot.Name;
                        if (!string.IsNullOrEmpty(hotdot.Tooltip))
                        {
                            ws.Cells[j, 2].AddComment("" + hotdot.Tooltip, "info");
                        }
                        ws.Cells[j, 2, j, 10].Merge = true;
                        ws.Cells[j, 11].Value       = double.Parse(buf.Value) / 100;
                        ws.Cells[j, 11].Style.Numberformat.Format = "0%";
                    }
                    border = ws.Cells[i + 3, 1, j, 11].Style.Border;
                    border.Bottom.Style  =
                        border.Top.Style = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;

                    AddCharts(ws, exdata, details, j);

                    ws.Column(1).Width = 5.6;
                    ws.Column(2).AutoFit();
                    ws.Column(3).AutoFit();
                    ws.Column(4).AutoFit();
                    ws.Column(5).AutoFit();
                    ws.Column(6).AutoFit();
                    ws.Column(7).AutoFit();
                    ws.Column(8).AutoFit();
                    ws.Column(9).AutoFit();
                    ws.Column(10).AutoFit();
                    ws.Column(11).Width = 20;
                    ws.Column(2).Width  = GetTrueColumnWidth(ws.Column(2).Width);
                    ws.Column(3).Width  = GetTrueColumnWidth(ws.Column(3).Width);
                    ws.Column(4).Width  = GetTrueColumnWidth(ws.Column(4).Width);
                    ws.Column(5).Width  = GetTrueColumnWidth(ws.Column(5).Width);
                    ws.Column(6).Width  = GetTrueColumnWidth(ws.Column(6).Width);
                    ws.Column(7).Width  = GetTrueColumnWidth(ws.Column(7).Width);
                    ws.Column(8).Width  = GetTrueColumnWidth(ws.Column(8).Width);
                    ws.Column(9).Width  = GetTrueColumnWidth(ws.Column(9).Width);
                    ws.Column(10).Width = GetTrueColumnWidth(ws.Column(10).Width);
                    ws.Cells[1, 1, j, 11].Style.VerticalAlignment   = ExcelVerticalAlignment.Center;
                    ws.Cells[1, 1, j, 11].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    ws.PrinterSettings.FitToPage = true;

                    // I don't know why, but sometimes column height setting is lost.
                    for (var x = 1; x < j; ++x)
                    {
                        ws.Row(x).CustomHeight = true;
                        ws.Row(x).Height       = 30;
                    }

                    ws.View.TabSelected = true;
                    details.Hidden      = eWorkSheetHidden.Hidden;
                    package.Workbook.Properties.Title   = Boss.Name;
                    package.Workbook.Properties.Author  = "ShinraMeter " + UpdateManager.Version;
                    package.Workbook.Properties.Company = "github.com/neowutran & github.com/Gl0";
                    package.Save();
                }
            }
        }
예제 #4
0
        private static void AddCharts(ExcelWorksheet ws, ExtendedStats exdata, ExcelWorksheet details, int startrow)
        {
            var time      = (int)(exdata.LastTick / TimeSpan.TicksPerSecond - exdata.FirstTick / TimeSpan.TicksPerSecond);
            var offset    = exdata.PlayerBuffs.Keys.ToList().IndexOf(ws.Name) + 1;
            var bossSheet = ws.Name == LP.Boss;

            if (!bossSheet && offset <= 0)
            {
                return;                            //no buff data for user -> no graphs.
            }
            offset = bossSheet ? 3 : 4 + offset * 7;
            var dps = ws.Drawings.AddChart(ws.Name + LP.Dps, eChartType.Line);

            dps.SetPosition(startrow + 1, 5, 0, 5);
            dps.SetSize(1200, 300);
            dps.Legend.Position = eLegendPosition.Top;
            if (time > 40)
            {
                dps.XAxis.MajorUnit = time / 20;
            }
            ExcelChart      typeDmg;
            ExcelChartSerie serieDmg;

            if (!bossSheet)
            {
                typeDmg = dps.PlotArea.ChartTypes[0];
                typeDmg.YAxis.Title.Text     = LP.Damage;
                typeDmg.YAxis.Title.Rotation = 90;

                serieDmg = typeDmg.Series.Add(details.Cells[3, offset + 5, time + 3, offset + 5],
                                              details.Cells[3, 2, time + 3, 2]);
                serieDmg.Header = ws.Name + " " + LP.Damage;
            }
            else
            {
                typeDmg = dps.PlotArea.ChartTypes[0];
                typeDmg.YAxis.Title.Text     = LP.BossHP;
                typeDmg.YAxis.Title.Rotation = 90;
                typeDmg.YAxis.MaxValue       = 1;
                serieDmg        = typeDmg.Series.Add(details.Cells[3, offset + 7, time + 3, offset + 7], details.Cells[3, 2, time + 3, 2]);
                serieDmg.Header = LP.BossHP + " %";
            }
            typeDmg.YAxis.MinValue = 0;
            var typeDps = dps.PlotArea.ChartTypes.Add(eChartType.Line);

            typeDps.UseSecondaryAxis     = true;
            typeDps.YAxis.Title.Text     = LP.AvgDPS;
            typeDps.YAxis.Title.Rotation = 90;
            typeDps.YAxis.SourceLinked   = false;
            typeDps.YAxis.Format         = @"#,#0\k\/\s"; //not sure why, but it loss sourcelink itself if we show only dps.
            var serieDps = typeDps.Series.Add(details.Cells[3, offset + 6, time + 3, offset + 6],
                                              details.Cells[3, 2, time + 3, 2]);

            serieDps.Header = ws.Name + " " + LP.AvgDPS;
            if (bossSheet)
            {
                typeDps.YAxis.MaxValue = details.Cells[3, offset + 6, time + 3, offset + 6].Max(x => (long)x.Value);
                typeDps.YAxis.MinValue = 0;
                int col = 4;
                foreach (var user in exdata.PlayerBuffs)
                {
                    col += 7;
                    //var userDmg = typeDmg.Series.Add(details.Cells[3, col + 5, time + 3, col + 5], details.Cells[3, 2, time + 3, 2]);
                    //userDmg.Header = user.Key + " Dmg";
                    var userDps = typeDps.Series.Add(details.Cells[3, col + 6, time + 3, col + 6],
                                                     details.Cells[3, 2, time + 3, 2]);
                    userDps.Header = user.Key + " " + LP.AvgDPS;
                }
            }
            //dps.FixEppPlusBug();// needed only if adding users dmg to main boss chart

            var numInt = bossSheet
                ? exdata.Debuffs.Sum(x => x.Value.Count()) - 1
                : exdata.PlayerBuffs[ws.Name].Times.Sum(x => x.Value.Count())
                         + exdata.PlayerBuffs[ws.Name].Death.Count()
                         + exdata.PlayerBuffs[ws.Name].Aggro(exdata.Entity).Count()
                         - 1;
            var numBuff = bossSheet
                ? exdata.Debuffs.Count
                : exdata.PlayerBuffs[ws.Name].Times.Count(x => x.Value.Count() > 0)
                          + (exdata.PlayerBuffs[ws.Name].Death.Count() > 0 ? 1 : 0)
                          + (exdata.PlayerBuffs[ws.Name].Aggro(exdata.Entity).Count() > 0 ? 1 : 0);

            if (numInt >= 0 && numBuff > 0)
            {
                var buff     = ws.Drawings.AddChart(ws.Name + LP.Buff, eChartType.BarStacked);
                var typeBuff = buff.PlotArea.ChartTypes[0];
                buff.SetPosition(startrow + 9, 5, 0, 5);
                buff.SetSize(1200, numBuff * 25 + 38);
                buff.Legend.Remove();
                var serieStart = typeBuff.Series.Add(details.Cells[3, offset + 1, numInt + 3, offset + 1],
                                                     details.Cells[3, offset, numInt + 3, offset]);
                serieStart.Header = LP.Start;
                (buff as ExcelBarChart).InvisibleSerie(serieStart);
                var serieTime = typeBuff.Series.Add(details.Cells[3, offset + 2, numInt + 3, offset + 2],
                                                    details.Cells[3, offset, numInt + 3, offset]);
                serieTime.Header             = LP.Time;
                typeBuff.YAxis.MajorUnit     = time >= 40 ? (double)(time / 20) / 86400F : 1F / 86400F;
                typeBuff.YAxis.MinValue      = 0F;
                typeBuff.YAxis.MaxValue      = (double)time / 86400F;
                typeBuff.XAxis.Orientation   = eAxisOrientation.MaxMin;
                typeBuff.XAxis.MinorTickMark = eAxisTickMark.None;
                typeBuff.YAxis.Crosses       = eCrosses.Max;
                var typeAxis = buff.PlotArea.ChartTypes.Add(eChartType.BarStacked);
                typeAxis.UseSecondaryAxis = true;
                var serieAxis = typeAxis.Series.Add(details.Cells[3, offset + 4, numBuff - 1 + 3, offset + 4],
                                                    details.Cells[3, offset + 3, numBuff - 1 + 3, offset + 3]);
                serieAxis.Header                 = LP.Name;
                typeAxis.XAxis.Orientation       = eAxisOrientation.MaxMin;
                typeAxis.XAxis.TickLabelPosition = eTickLabelPosition.NextTo;
                typeAxis.XAxis.MinorTickMark     = eAxisTickMark.None;
                typeAxis.YAxis.Deleted           = true;
                typeAxis.XAxis.Deleted           = false;
                (buff as ExcelBarChart).FirstAxisDate(numBuff);
                //buff.FixEppPlusBug();
            }
        }
예제 #5
0
        private static ExtendedStats GenerateStats(NpcEntity entity, AbnormalityStorage abnormals)
        {
            if (!entity.Info.Boss)
            {
                return(null);
            }

            var timedEncounter = false;

            /*
             * modify timedEncounter depending on teradps.io need
             *
             */

            var entityInfo  = Database.Database.Instance.GlobalInformationEntity(entity, timedEncounter);
            var skills      = Database.Database.Instance.GetSkills(entityInfo.BeginTime, entityInfo.EndTime);
            var playersInfo = timedEncounter
                ? Database.Database.Instance.PlayerDamageInformation(entityInfo.BeginTime, entityInfo.EndTime)
                : Database.Database.Instance.PlayerDamageInformation(entity);
            var heals = Database.Database.Instance.PlayerHealInformation(entityInfo.BeginTime, entityInfo.EndTime);

            playersInfo.RemoveAll(x => x.Amount == 0);

            var firstTick = entityInfo.BeginTime;
            var lastTick  = entityInfo.EndTime;
            var interTick = lastTick - firstTick;
            var interval  = interTick / TimeSpan.TicksPerSecond;

            if (interval == 0)
            {
                return(null);
            }
            var totaldamage = entityInfo.TotalDamage;
            var partyDps    = TimeSpan.TicksPerSecond * totaldamage / interTick;

            var teradpsData   = new EncounterBase();
            var extendedStats = new ExtendedStats();
            var _abnormals    = abnormals.Clone(entity, firstTick, lastTick);

            extendedStats.Entity      = entity;
            extendedStats.BaseStats   = teradpsData;
            extendedStats.FirstTick   = firstTick;
            extendedStats.LastTick    = lastTick;
            teradpsData.areaId        = entity.Info.HuntingZoneId + "";
            teradpsData.bossId        = entity.Info.TemplateId + "";
            teradpsData.fightDuration = interval + "";
            teradpsData.partyDps      = partyDps + "";
            extendedStats.Debuffs     = _abnormals.Get(entity);

            foreach (var debuff in extendedStats.Debuffs)
            {
                var percentage = debuff.Value.Duration(firstTick, lastTick) * 100 / interTick;
                if (percentage == 0)
                {
                    continue;
                }
                teradpsData.debuffUptime.Add(new KeyValuePair <string, string>(
                                                 debuff.Key.Id + "", percentage + ""
                                                 ));
            }

            foreach (var user in playersInfo)
            {
                var teradpsUser = new Members();
                var damage      = user.Amount;
                teradpsUser.playerTotalDamage = damage + "";

                if (damage <= 0)
                {
                    continue;
                }

                var buffs = _abnormals.Get(user.Source);
                teradpsUser.playerClass           = user.Source.Class.ToString();
                teradpsUser.playerName            = user.Source.Name;
                teradpsUser.playerServer          = BasicTeraData.Instance.Servers.GetServerName(user.Source.ServerId);
                teradpsUser.playerAverageCritRate = Math.Round(user.CritRate, 1) + "";
                teradpsUser.healCrit = user.Source.IsHealer
                    ? heals.FirstOrDefault(x => x.Source == user.Source)?.CritRate + ""
                    : null;
                teradpsUser.playerDps = TimeSpan.TicksPerSecond * damage / interTick + "";
                teradpsUser.playerTotalDamagePercentage = user.Amount * 100 / entityInfo.TotalDamage + "";

                extendedStats.PlayerReceived.Add(user.Source.Name, Tuple.Create(skills.HitsReceived(user.Source.User.Id, entity, timedEncounter), skills.DamageReceived(user.Source.User.Id, entity, timedEncounter)));

                var death = buffs.Death;
                teradpsUser.playerDeaths        = death.Count(firstTick, lastTick) + "";
                teradpsUser.playerDeathDuration = death.Duration(firstTick, lastTick) / TimeSpan.TicksPerSecond + "";

                var aggro = buffs.Aggro(entity);
                teradpsUser.aggro = 100 * aggro.Duration(firstTick, lastTick) / interTick + "";

                foreach (var buff in buffs.Times)
                {
                    var percentage = buff.Value.Duration(firstTick, lastTick) * 100 / interTick;
                    if (percentage == 0)
                    {
                        continue;
                    }
                    teradpsUser.buffUptime.Add(new KeyValuePair <string, string>(
                                                   buff.Key.Id + "", percentage + ""
                                                   ));
                }
                var serverPlayerName = $"{teradpsUser.playerServer}_{teradpsUser.playerName}";
                extendedStats.PlayerSkills.Add(serverPlayerName,
                                               skills.GetSkillsDealt(user.Source.User.Id, entity, timedEncounter));
                extendedStats.PlayerBuffs.Add(serverPlayerName, buffs);

                var skillsId = SkillAggregate.GetAggregate(user, entityInfo.Entity, skills, timedEncounter, Database.Database.Type.Damage);
                extendedStats.PlayerSkillsAggregated[teradpsUser.playerServer + "/" + teradpsUser.playerName] = skillsId;

                foreach (var skill in skillsId)
                {
                    var skillLog    = new SkillLog();
                    var skilldamage = skill.Amount();

                    skillLog.skillAverageCrit   = Math.Round(skill.AvgCrit()) + "";
                    skillLog.skillAverageWhite  = Math.Round(skill.AvgWhite()) + "";
                    skillLog.skillCritRate      = skill.CritRate() + "";
                    skillLog.skillDamagePercent = skill.DamagePercent() + "";
                    skillLog.skillHighestCrit   = skill.BiggestCrit() + "";
                    skillLog.skillHits          = skill.Hits() + "";
                    skillLog.skillId            = skill.Skills.First().Key.Id + "";
                    skillLog.skillLowestCrit    = skill.LowestCrit() + "";
                    skillLog.skillTotalDamage   = skilldamage + "";


                    if (skilldamage == 0)
                    {
                        continue;
                    }
                    teradpsUser.skillLog.Add(skillLog);
                }
                teradpsData.members.Add(teradpsUser);
            }
            return(extendedStats);
        }
예제 #6
0
        private static ExtendedStats GenerateStats(NpcEntity entity, AbnormalityStorage abnormals)
        {
            if (!entity.Info.Boss)
            {
                return(null);
            }

            var timedEncounter = false;

            /*
             * modify timedEncounter depending on teradps.io need
             *
             */

            var entityInfo  = Database.Database.Instance.GlobalInformationEntity(entity, timedEncounter);
            var skills      = Database.Database.Instance.GetSkills(entityInfo.BeginTime, entityInfo.EndTime);
            var playersInfo = timedEncounter
                ? Database.Database.Instance.PlayerDamageInformation(entityInfo.BeginTime, entityInfo.EndTime)
                : Database.Database.Instance.PlayerDamageInformation(entity);
            var heals = Database.Database.Instance.PlayerHealInformation(entityInfo.BeginTime, entityInfo.EndTime);

            playersInfo.RemoveAll(x => x.Amount == 0);

            var firstTick = entityInfo.BeginTime;
            var lastTick  = entityInfo.EndTime;
            var interTick = lastTick - firstTick;
            var interval  = interTick / TimeSpan.TicksPerSecond;

            if (interval == 0)
            {
                return(null);
            }
            var totaldamage = entityInfo.TotalDamage;
            var partyDps    = TimeSpan.TicksPerSecond * totaldamage / interTick;

            var teradpsData   = new EncounterBase();
            var extendedStats = new ExtendedStats();
            var _abnormals    = abnormals.Clone(entity, firstTick, lastTick);

            teradpsData.encounterUnixEpoch = new DateTimeOffset(new DateTime(lastTick, DateTimeKind.Utc)).ToUnixTimeSeconds();
            extendedStats.Entity           = entity;
            extendedStats.BaseStats        = teradpsData;
            extendedStats.FirstTick        = firstTick;
            extendedStats.LastTick         = lastTick;
            teradpsData.areaId             = entity.Info.HuntingZoneId + "";
            teradpsData.bossId             = entity.Info.TemplateId + "";
            teradpsData.fightDuration      = interval + "";
            teradpsData.partyDps           = partyDps + "";
            extendedStats.Debuffs          = _abnormals.Get(entity);

            foreach (var debuff in extendedStats.Debuffs.OrderByDescending(x => x.Value.Duration(firstTick, lastTick)))
            {
                var percentage = debuff.Value.Duration(firstTick, lastTick) * 100 / interTick;
                if (percentage == 0)
                {
                    continue;
                }
                teradpsData.debuffUptime.Add(new KeyValuePair <string, string>(
                                                 debuff.Key.Id + "", percentage + ""
                                                 ));
                var stacks = new List <List <int> > {
                    new List <int> {
                        0, (int)percentage
                    }
                };
                var stackList = debuff.Value.Stacks(firstTick, lastTick).OrderBy(x => x);
                teradpsData.debuffDetail.Add(new List <object> {
                    debuff.Key.Id, stacks
                });
                if (stackList.Any() && stackList.Max() == 1)
                {
                    continue;
                }
                foreach (var stack in stackList)
                {
                    percentage = debuff.Value.Duration(firstTick, lastTick, stack) * 100 / interTick;
                    if (percentage == 0)
                    {
                        continue;
                    }
                    stacks.Add(new List <int> {
                        stack, (int)percentage
                    });
                }
            }

            foreach (var user in playersInfo.OrderByDescending(x => x.Amount))
            {
                var teradpsUser = new Members();
                var damage      = user.Amount;
                teradpsUser.playerTotalDamage = damage + "";

                if (damage <= 0)
                {
                    continue;
                }

                var buffs = _abnormals.Get(user.Source);
                teradpsUser.guild                 = string.IsNullOrWhiteSpace(user.Source.GuildName) ? null : user.Source.GuildName;
                teradpsUser.playerClass           = user.Source.Class.ToString();
                teradpsUser.playerName            = user.Source.Name;
                teradpsUser.playerId              = user.Source.PlayerId;
                teradpsUser.playerServer          = BasicTeraData.Instance.Servers.GetServerName(user.Source.ServerId);
                teradpsUser.playerAverageCritRate = Math.Round(user.CritRate, 1) + "";
                teradpsUser.healCrit              = user.Source.IsHealer
                    ? heals.FirstOrDefault(x => x.Source == user.Source)?.CritRate + ""
                    : null;
                teradpsUser.playerDps = TimeSpan.TicksPerSecond * damage / interTick + "";
                teradpsUser.playerTotalDamagePercentage = user.Amount * 100 / entityInfo.TotalDamage + "";

                extendedStats.PlayerReceived.Add(user.Source.Name, Tuple.Create(skills.HitsReceived(user.Source.User, entity, timedEncounter), skills.DamageReceived(user.Source.User, entity, timedEncounter)));
                extendedStats.PlayerCritDamageRate.Add(user.Source.Name, user.CritDamageRate);

                var death = buffs.Death;
                teradpsUser.playerDeaths        = death.Count(firstTick, lastTick) + "";
                teradpsUser.playerDeathDuration = death.Duration(firstTick, lastTick) / TimeSpan.TicksPerSecond + "";

                var aggro = buffs.Aggro(entity);
                teradpsUser.aggro = 100 * aggro.Duration(firstTick, lastTick) / interTick + "";

                foreach (var buff in buffs.Times.OrderByDescending(x => x.Value.Duration(firstTick, lastTick)))
                {
                    var percentage = buff.Value.Duration(firstTick, lastTick) * 100 / interTick;
                    if (percentage == 0)
                    {
                        continue;
                    }
                    teradpsUser.buffUptime.Add(new KeyValuePair <string, string>(
                                                   buff.Key.Id + "", percentage + ""
                                                   ));
                    var stacks = new List <List <int> > {
                        new List <int> {
                            0, (int)percentage
                        }
                    };
                    var stackList = buff.Value.Stacks(firstTick, lastTick).OrderBy(x => x);
                    teradpsUser.buffDetail.Add(new List <object> {
                        buff.Key.Id, stacks
                    });
                    if (stackList.Any() && stackList.Max() == 1)
                    {
                        continue;
                    }
                    foreach (var stack in buff.Value.Stacks(firstTick, lastTick).OrderBy(x => x))
                    {
                        percentage = buff.Value.Duration(firstTick, lastTick, stack) * 100 / interTick;
                        if (percentage == 0)
                        {
                            continue;
                        }
                        stacks.Add(new List <int> {
                            stack, (int)percentage
                        });
                    }
                }
                var serverPlayerName = $"{teradpsUser.playerServer}_{teradpsUser.playerName}";
                extendedStats.PlayerSkills.Add(serverPlayerName,
                                               skills.GetSkillsDealt(user.Source.User, entity, timedEncounter));
                extendedStats.PlayerBuffs.Add(serverPlayerName, buffs);

                var skillsId = SkillAggregate.GetAggregate(user, entityInfo.Entity, skills, timedEncounter, Database.Database.Type.Damage);
                extendedStats.PlayerSkillsAggregated[teradpsUser.playerServer + "/" + teradpsUser.playerName] = skillsId;

                foreach (var skill in skillsId.OrderByDescending(x => x.Amount()))
                {
                    var skillLog    = new SkillLog();
                    var skilldamage = skill.Amount();

                    skillLog.skillAverageCrit   = Math.Round(skill.AvgCrit()) + "";
                    skillLog.skillAverageWhite  = Math.Round(skill.AvgWhite()) + "";
                    skillLog.skillCritRate      = skill.CritRate() + "";
                    skillLog.skillDamagePercent = skill.DamagePercent() + "";
                    skillLog.skillHighestCrit   = skill.BiggestCrit() + "";
                    skillLog.skillHits          = skill.Hits() + "";
                    var skillKey = skill.Skills.First().Key;
                    skillLog.skillId          = BasicTeraData.Instance.SkillDatabase.GetSkillByPetName(skillKey.NpcInfo?.Name, user.Source.RaceGenderClass)?.Id.ToString() ?? skillKey.Id.ToString();
                    skillLog.skillLowestCrit  = skill.LowestCrit() + "";
                    skillLog.skillTotalDamage = skilldamage + "";


                    if (skilldamage == 0)
                    {
                        continue;
                    }
                    teradpsUser.skillLog.Add(skillLog);
                }
                if (NetworkController.Instance.MeterPlayers.Contains(user.Source))
                {
                    teradpsData.uploader = teradpsData.members.Count.ToString();
                }
                teradpsData.members.Add(teradpsUser);
            }
            return(extendedStats);
        }
예제 #7
0
        private static ExcelHyperLink CreateUserSheet(ExcelWorkbook wb, Members user, ExtendedStats exdata, ExcelWorksheet details)
        {
            ExcelWorksheet ws  = wb.Worksheets.Add($"{user.playerServer}_{user.playerName}");
            var            rgc = new RaceGenderClass("Common", "Common", user.playerClass);

            ws.DefaultRowHeight      = 30;
            ws.Cells.Style.Font.Size = 14;
            ws.Cells.Style.Font.Name = "Arial";
            AddImage(ws, 1, 1, ClassIcons.Instance.GetBitmap((PlayerClass)Enum.Parse(typeof(PlayerClass), user.playerClass)));
            ws.Cells[1, 2].Value                  = $"{user.playerServer}: {user.playerName}";
            ws.Cells[1, 2, 1, 10].Merge           = true;
            ws.Cells[1, 2, 1, 10].Style.Font.Bold = true;
            ws.Cells[2, 2].Value                  = "Skill";
            ws.Cells[2, 3].Value                  = "Damage %";
            ws.Cells[2, 4].Value                  = "Damage";
            ws.Cells[2, 5].Value                  = "Crit %";
            ws.Cells[2, 6].Value                  = "Hits";
            ws.Cells[2, 7].Value                  = "Max Crit";
            ws.Cells[2, 8].Value                  = "Min Crit";
            ws.Cells[2, 9].Value                  = "Avg Crit";
            ws.Cells[2, 10].Value                 = "Avg White";
            int i = 2;

            foreach (var stat in user.skillLog.OrderByDescending(x => long.Parse(x.skillTotalDamage)))
            {
                i++;
                var skill = BTD.SkillDatabase.GetOrNull(rgc, int.Parse(stat.skillId));
                if (skill == null)
                {
                    ws.Cells[i, 1].Value = i - 2;
                    ws.Cells[i, 2].Value = "Some pet skill";
                }
                else
                {
                    ws.Cells[i, 1].Value = i - 2;
                    AddImage(ws, i, 1, BTD.Icons.GetBitmap(skill.IconName));
                    ws.Cells[i, 2].Value = skill.Name;
                }
                ws.Cells[i, 3].Value = double.Parse(stat.skillDamagePercent) / 100;
                ws.Cells[i, 3].Style.Numberformat.Format = "0.0%";
                ws.Cells[i, 4].Value = long.Parse(stat.skillTotalDamage);
                ws.Cells[i, 4].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 5].Value = double.Parse(stat.skillCritRate) / 100;
                ws.Cells[i, 5].Style.Numberformat.Format = "0.0%";
                ws.Cells[i, 6].Value = long.Parse(stat.skillHits);
                ws.Cells[i, 7].Value = long.Parse(stat.skillHighestCrit);
                ws.Cells[i, 7].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 8].Value = long.Parse(stat.skillLowestCrit);
                ws.Cells[i, 8].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 9].Value = long.Parse(stat.skillAverageCrit);
                ws.Cells[i, 9].Style.Numberformat.Format = @"#,#0,\k";
                ws.Cells[i, 10].Value = long.Parse(stat.skillAverageWhite);
                ws.Cells[i, 10].Style.Numberformat.Format = @"#,#0,\k";
            }
            var border = ws.Cells[1, 1, i, 10].Style.Border;

            border.Bottom.Style = border.Top.Style = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;
            ws.Cells[2, 1, i, 10].AutoFilter = true;

            int j = i + 3;

            ws.Cells[j, 2].Value                  = "Buff name";
            ws.Cells[j, 2, j, 9].Merge            = true;
            ws.Cells[j, 10].Value                 = "%";
            ws.Cells[j, 2, j, 10].Style.Font.Bold = true;
            foreach (var buf in user.buffUptime)
            {
                j++;
                var hotdot = BTD.HotDotDatabase.Get(int.Parse(buf.Key));
                ws.Cells[j, 1].Value = j - i - 3;
                AddImage(ws, j, 1, BTD.Icons.GetBitmap(hotdot.IconName));
                ws.Cells[j, 2].Value = hotdot.Name;
                if (!string.IsNullOrEmpty(hotdot.Tooltip))
                {
                    ws.Cells[j, 2].AddComment("" + hotdot.Tooltip, "info");
                }
                ws.Cells[j, 2, j, 9].Merge = true;
                ws.Cells[j, 10].Value      = double.Parse(buf.Value) / 100;
                ws.Cells[j, 10].Style.Numberformat.Format = "0%";
                if (!string.IsNullOrEmpty(hotdot.ItemName))
                {
                    ws.Cells[j, 10].AddComment("" + hotdot.ItemName, "info");
                }
            }
            border = ws.Cells[i + 3, 1, j, 10].Style.Border;
            border.Bottom.Style = border.Top.Style = border.Left.Style = border.Right.Style = ExcelBorderStyle.Thick;

            AddCharts(ws, exdata, details, j);

            ws.Column(1).Width = 5.6;
            ws.Column(2).AutoFit();
            ws.Column(3).AutoFit();
            ws.Column(4).AutoFit();
            ws.Column(5).AutoFit();
            ws.Column(6).AutoFit();
            ws.Column(7).AutoFit();
            ws.Column(8).AutoFit();
            ws.Column(9).AutoFit();
            ws.Column(10).AutoFit();
            ws.Column(2).Width  = GetTrueColumnWidth(ws.Column(2).Width);
            ws.Column(3).Width  = GetTrueColumnWidth(ws.Column(3).Width);
            ws.Column(4).Width  = GetTrueColumnWidth(ws.Column(4).Width);
            ws.Column(5).Width  = GetTrueColumnWidth(ws.Column(5).Width);
            ws.Column(6).Width  = GetTrueColumnWidth(ws.Column(6).Width);
            ws.Column(7).Width  = GetTrueColumnWidth(ws.Column(7).Width);
            ws.Column(8).Width  = GetTrueColumnWidth(ws.Column(8).Width);
            ws.Column(9).Width  = GetTrueColumnWidth(ws.Column(9).Width);
            ws.Column(10).Width = GetTrueColumnWidth(ws.Column(10).Width);
            ws.Cells[1, 1, j, 10].Style.VerticalAlignment   = ExcelVerticalAlignment.Center;
            ws.Cells[1, 1, j, 10].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
            ws.PrinterSettings.FitToPage = true;
            return(new ExcelHyperLink($"{user.playerServer}_{user.playerName}!A1", $"{user.playerServer}: {user.playerName}"));
        }
예제 #8
0
        public static void JsonSave(ExtendedStats exdata, string userName = "", bool manual = false)
        {
            if (!BTD.WindowData.Json && !manual)
            {
                return;
            }

            var data = exdata.BaseStats;
            var Boss = exdata.Entity.Info;

            /*
             * Select save directory
             */
            var fileName = BTD.WindowData.ExcelPathTemplate.Replace("{Area}", Boss.Area.Replace(":", "-")).Replace("{Boss}", Boss.Name.Replace(":", "-"))
                           .Replace("{Date}", DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture))
                           .Replace("{Time}", DateTime.Now.ToString("HH-mm-ss", CultureInfo.InvariantCulture))
                           .Replace("{User}", string.IsNullOrEmpty(userName) ? "_____" : userName) + ".7z";

            var fname = Path.Combine(BTD.WindowData.ExcelSaveDirectory, fileName);

            /*
             * Test if you have access to the user choice directory, if not, switch back to the default save directory
             */
            try { Directory.CreateDirectory(Path.GetDirectoryName(fname)); }
            catch {
                fname = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
                Directory.CreateDirectory(Path.GetDirectoryName(fname));
            }

            var file = new FileInfo(fname);

            if (file.Exists)
            {
                return;
            }
            //the only case this can happen is BAM mobtraining, that's not so interesting statistic to deal with more complex file names.

            var jsonData = new JsonData();

            jsonData.areaId             = data.areaId;
            jsonData.bossId             = data.bossId;
            jsonData.encounterUnixEpoch = data.encounterUnixEpoch.ToString();
            jsonData.fightDuration      = data.fightDuration;
            jsonData.partyDps           = data.partyDps;
            foreach (var entity in exdata.AllSkills.GetEntities())
            {
                var e = entity as NpcEntity;
                if (e != null)
                {
                    var mob = new JsonMob();
                    mob.entityId      = e.Id.Id.ToString();
                    mob.huntingZoneId = e.Info.HuntingZoneId;
                    mob.templateId    = e.Info.TemplateId;
                    var abnormals = exdata.Abnormals.Get(e);
                    foreach (var abnormal in abnormals)
                    {
                        foreach (var duration in abnormal.Value.AllDurations())
                        {
                            mob.abnormals.Add(new JsonAbnormal()
                            {
                                id    = abnormal.Key.Id,
                                start = (int)((duration.Begin - exdata.FirstTick) / TimeSpan.TicksPerMillisecond),
                                end   = (int)((duration.End - exdata.FirstTick) / TimeSpan.TicksPerMillisecond),
                                stack = duration.Stack
                            });
                        }
                    }

                    jsonData.mobs.Add(mob);
                }
            }

            foreach (var member in data.members)
            {
                var player     = PacketProcessor.Instance.PlayerTracker.Get(member.playerServerId, member.playerId);
                var jsonMember = new JsonMember();
                jsonMember.entityId                    = player.User.Id.Id.ToString();
                jsonMember.templateId                  = player.RaceGenderClass.Raw;
                jsonMember.playerServerId              = member.playerServerId;
                jsonMember.playerId                    = member.playerId;
                jsonMember.playerServer                = member.playerServer;
                jsonMember.playerName                  = member.playerName;
                jsonMember.playerClass                 = member.playerClass;
                jsonMember.guild                       = member.guild;
                jsonMember.aggro                       = member.aggro;
                jsonMember.healCrit                    = member.healCrit;
                jsonMember.playerDeaths                = member.playerDeaths;
                jsonMember.playerDeathDuration         = member.playerDeathDuration;
                jsonMember.playerDps                   = member.playerDps;
                jsonMember.playerTotalDamage           = member.playerTotalDamage;
                jsonMember.playerTotalDamagePercentage = member.playerTotalDamagePercentage;
                jsonMember.playerAverageCritRate       = member.playerAverageCritRate;
                var skills = exdata.AllSkills.GetSkillsDealt(player.User, null, true).OrderBy(x => x.Time);
                foreach (var skill in skills)
                {
                    var jsonSkill = new JsonSkill();
                    jsonSkill.time    = (int)((skill.Time - exdata.FirstTick) / TimeSpan.TicksPerMillisecond);
                    jsonSkill.type    = (int)skill.Type;
                    jsonSkill.crit    = skill.Critic;
                    jsonSkill.dot     = skill.HotDot;
                    jsonSkill.skillId = BTD.SkillDatabase.GetSkillByPetName(skill.Pet?.Name, player.RaceGenderClass)?.Id ?? skill.SkillId;
                    jsonSkill.amount  = skill.Amount.ToString();
                    jsonSkill.target  = skill.Target.Id.Id == ulong.MaxValue ? null : skill.Target.Id.Id.ToString();
                    jsonMember.dealtSkillLog.Add(jsonSkill);
                }

                skills = exdata.AllSkills.GetSkillsReceived(player.User, true).OrderBy(x => x.Time);
                foreach (var skill in skills)
                {
                    var jsonSkill = new JsonSkill();
                    jsonSkill.time    = (int)((skill.Time - exdata.FirstTick) / TimeSpan.TicksPerMillisecond);
                    jsonSkill.type    = (int)skill.Type;
                    jsonSkill.crit    = skill.Critic;
                    jsonSkill.dot     = skill.HotDot;
                    jsonSkill.skillId = BTD.SkillDatabase.GetSkillByPetName(skill.Pet?.Name, player.RaceGenderClass)?.Id ?? skill.SkillId;
                    jsonSkill.amount  = skill.Amount.ToString();
                    jsonSkill.source  = skill.Source.Id.Id == ulong.MaxValue ? null : skill.Source.Id.Id.ToString();
                    jsonMember.receivedSkillLog.Add(jsonSkill);
                }

                var abnormals = exdata.Abnormals.Get(player);
                foreach (var abnormal in abnormals.Times)
                {
                    foreach (var duration in abnormal.Value.AllDurations())
                    {
                        jsonMember.abnormals.Add(new JsonAbnormal()
                        {
                            id    = abnormal.Key.Id,
                            start = (int)((duration.Begin - exdata.FirstTick) / TimeSpan.TicksPerMillisecond),
                            end   = (int)((duration.End - exdata.FirstTick) / TimeSpan.TicksPerMillisecond),
                            stack = duration.Stack
                        });
                    }
                }

                jsonData.players.Add(jsonMember);
            }

            Task.Run(() => {
                lock (savelock) //don't save 2 files at one time
                {
                    if (file.Exists)
                    {
                        return;
                    }                            //double check if file was created while we were preparing export in other thread

                    var libpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Environment.Is64BitProcess ? "lib/7z_x64.dll" : "lib/7z.dll");
                    SevenZipBase.SetLibraryPath(libpath);
                    var compressor = new SevenZipCompressor {
                        ArchiveFormat = OutArchiveFormat.SevenZip
                    };
                    compressor.CustomParameters["tc"] = "off";
                    compressor.CompressionLevel       = CompressionLevel.Ultra;
                    compressor.CompressionMode        = CompressionMode.Create;
                    compressor.TempFolderPath         = Path.GetTempPath();
                    compressor.PreserveDirectoryRoot  = false;
                    compressor.DefaultItemName        = Path.GetFileNameWithoutExtension(fileName) + ".json";
                    using MemoryStream s       = new MemoryStream();
                    using StreamWriter w       = new StreamWriter(s);
                    using JsonTextWriter jsonw = new JsonTextWriter(w);
                    JsonSerializer ser         = new JsonSerializer();
                    ser.NullValueHandling      = NullValueHandling.Ignore;
                    ser.Formatting             = Formatting.Indented;
                    ser.Serialize(jsonw, jsonData);
                    jsonw.Flush();
                    s.Position   = 0;
                    using var cs = File.Create(fname);
                    compressor.CompressStream(s, cs);
                }
            });
        }
예제 #9
0
        private static ExtendedStats GenerateStats(SDespawnNpc despawnNpc, AbnormalityStorage abnormals)
        {
            if (!despawnNpc.Dead)
            {
                return(null);
            }

            var entity = DamageTracker.Instance.GetEntity(despawnNpc.Npc);

            if (!entity.IsBoss || !DamageTracker.Instance.EntitiesStats.ContainsKey(entity))
            {
                return(null);
            }

            bool timedEncounter = false;

            //Nightmare desolarus
            if (entity.NpcE.Info.HuntingZoneId == 759 && entity.NpcE.Info.TemplateId == 1003)
            {
                timedEncounter = true;
            }

            var firstTick = DamageTracker.Instance.EntitiesStats[entity].FirstHit;
            var lastTick  = DamageTracker.Instance.EntitiesStats[entity].LastHit;
            var interTick = lastTick - firstTick;
            var interval  = interTick / TimeSpan.TicksPerSecond;

            if (interval == 0)
            {
                return(null);
            }
            var totaldamage = DamageTracker.Instance.TotalDamage(entity, timedEncounter);
            var partyDps    = TimeSpan.TicksPerSecond * totaldamage / interTick;

            var teradpsData   = new EncounterBase();
            var extendedStats = new ExtendedStats();
            var stats         = DamageTracker.Instance.GetPlayerStats();
            var _abnormals    = abnormals.Clone(entity.NpcE, firstTick, lastTick);

            extendedStats.Entity      = entity.NpcE;
            extendedStats.BaseStats   = teradpsData;
            extendedStats.FirstTick   = firstTick;
            extendedStats.LastTick    = lastTick;
            teradpsData.areaId        = entity.NpcE.Info.HuntingZoneId + "";
            teradpsData.bossId        = entity.NpcE.Info.TemplateId + "";
            teradpsData.fightDuration = interval + "";
            teradpsData.partyDps      = partyDps + "";
            extendedStats.Debuffs     = _abnormals.Get(entity.NpcE);

            foreach (var debuff in extendedStats.Debuffs)
            {
                long percentage = (debuff.Value.Duration(firstTick, lastTick) * 100 / interTick);
                if (percentage == 0)
                {
                    continue;
                }
                teradpsData.debuffUptime.Add(new KeyValuePair <string, string>(
                                                 debuff.Key.Id + "", percentage + ""
                                                 ));
            }

            foreach (var user in stats)
            {
                var teradpsUser = new Members();
                var damage      = user.Dealt.Damage(entity, timedEncounter);
                teradpsUser.playerTotalDamage = damage + "";

                if (damage <= 0)
                {
                    continue;
                }

                var buffs = _abnormals.Get(user.Player);
                teradpsUser.playerClass           = user.Class.ToString();
                teradpsUser.playerName            = user.Name;
                teradpsUser.playerServer          = BasicTeraData.Instance.Servers.GetServerName(user.Player.ServerId);
                teradpsUser.playerAverageCritRate = user.Dealt.CritRate(entity, timedEncounter) + "";
                teradpsUser.healCrit  = user.IsHealer ? user.Dealt.CritRateHeal(entity, timedEncounter) + "" : null;
                teradpsUser.playerDps = TimeSpan.TicksPerSecond * damage / interTick + "";
                teradpsUser.playerTotalDamagePercentage = user.Dealt.DamageFraction(entity, totaldamage, timedEncounter) + "";

                var death = buffs.Death;
                teradpsUser.playerDeaths        = death.Count(firstTick, lastTick) + "";
                teradpsUser.playerDeathDuration = death.Duration(firstTick, lastTick) / TimeSpan.TicksPerSecond + "";

                var aggro = buffs.Aggro(entity.NpcE);
                teradpsUser.aggro = 100 * aggro.Duration(firstTick, lastTick) / interTick + "";

                foreach (var buff in buffs.Times)
                {
                    long percentage = (buff.Value.Duration(firstTick, lastTick) * 100 / interTick);
                    if (percentage == 0)
                    {
                        continue;
                    }
                    teradpsUser.buffUptime.Add(new KeyValuePair <string, string>(
                                                   buff.Key.Id + "", percentage + ""
                                                   ));
                }
                var serverPlayerName = $"{teradpsUser.playerServer}_{teradpsUser.playerName}";
                extendedStats.PlayerSkills.Add(serverPlayerName, timedEncounter ? user.Dealt.GetSkillsByTime(entity) : user.Dealt.GetSkills(entity));
                extendedStats.PlayerBuffs.Add(serverPlayerName, buffs);
                var notimedskills = NoTimedSkills(extendedStats.PlayerSkills[serverPlayerName]);

                foreach (var skill in notimedskills)
                {
                    var skillLog    = new SkillLog();
                    var skilldamage = skill.Value.Damage;

                    skillLog.skillAverageCrit   = skill.Value.DmgAverageCrit + "";
                    skillLog.skillAverageWhite  = skill.Value.DmgAverageHit + "";
                    skillLog.skillCritRate      = skill.Value.CritRateDmg + "";
                    skillLog.skillDamagePercent = skill.Value.DamagePercentage(entity, timedEncounter) + "";
                    skillLog.skillHighestCrit   = skill.Value.DmgBiggestCrit + "";
                    skillLog.skillHits          = skill.Value.HitsDmg + "";
                    skillLog.skillId            = BasicTeraData.Instance.SkillDatabase.GetSkillByPetName(skill.Key.NpcInfo?.Name, user.Player.RaceGenderClass)?.Id.ToString() ?? skill.Key.SkillId.ElementAt(0).ToString();
                    skillLog.skillLowestCrit    = skill.Value.DmgLowestCrit + "";
                    skillLog.skillTotalDamage   = skilldamage + "";

                    if (skilldamage == 0)
                    {
                        continue;
                    }
                    teradpsUser.skillLog.Add(skillLog);
                }
                teradpsData.members.Add(teradpsUser);
            }
            return(extendedStats);
        }