private void FillMobsList() { mobList.Items.Clear(); oldIndices.Clear(); // Get data from Mob XP Handler to add mob entries to the checked item list. MobFilter mobFilter = MobXPHandler.Instance.CustomMobFilter; string mobString; var mobXPVals = MobXPHandler.Instance.CompleteMobList; foreach (var mob in mobXPVals) { mobString = string.Format("{2} - {0} ({1})", mob.Name, mob.BaseXP, mob.BattleID); mobList.Items.Add(mobString); } // If the filter has any data in it, check those mobs for (int i = 0; i < mobList.Items.Count; i++) { if (mobFilter.CustomBattleIDs.Contains(mobXPVals.ElementAt(i).BattleID)) { mobList.SetSelected(i, true); } } }
/// <summary> /// Extension function to extract out formatted mob list info from a /// drop-down combo box. /// </summary> /// <param name="combo">The combo box with formatted mob names in it.</param> /// <param name="include0XPMobs">Flag to tell whether 0 XP mobs should be included (only relevent to All).</param> /// <returns>Returns a MobFilter object containing the relevant filter information.</returns> public static MobFilter CBGetMobFilter(this ToolStripComboBox combo, bool exclude0XPMobs) { if (combo.ComboBox.InvokeRequired) { Func <ToolStripComboBox, MobFilter> thisFunc = CBGetMobFilter; return((MobFilter)combo.ComboBox.Invoke(thisFunc, new object[] { combo })); } MobFilter filter = new MobFilter { AllMobs = true, GroupMobs = false, FightNumber = 0, MobName = "", MobXP = -1, Exclude0XPMobs = exclude0XPMobs, CustomSelection = false }; if (combo.SelectedIndex >= 0) { string filterText = combo.SelectedItem.ToString(); if (filterText != "All") { Regex mobBattle = new Regex(@"\s*(?<battleID>\d+):\s+(?<mobName>.*)"); Match mobBattleMatch = mobBattle.Match(filterText); if (mobBattleMatch.Success == true) { filter.AllMobs = false; filter.GroupMobs = false; filter.MobName = mobBattleMatch.Groups["mobName"].Value; filter.FightNumber = int.Parse(mobBattleMatch.Groups["battleID"].Value); return(filter); } Regex mobAndXP = new Regex(@"((?<mobName>.*(?<! \())) \(((?<xp>\d+)\))|(?<mobName>.*)"); Match mobAndXPMatch = mobAndXP.Match(filterText); if (mobAndXPMatch.Success == true) { filter.AllMobs = false; filter.GroupMobs = true; filter.MobName = mobAndXPMatch.Groups["mobName"].Value; if ((mobAndXPMatch.Groups["xp"] != null) && (mobAndXPMatch.Groups["xp"].Value != string.Empty)) { filter.MobXP = int.Parse(mobAndXPMatch.Groups["xp"].Value); } else { filter.MobXP = -1; } } } } return(filter); }
// List box event handlers private void mobList_SelectedIndexChanged(object sender, EventArgs e) { // Flag to prevent processing of this section of code if we're // using one of the predefined event handler functions below. if (checkingMobList) { return; } MobFilter mobFilter = MobXPHandler.Instance.CustomMobFilter; // List of which entries in the mob list are currently selected. var indices = mobList.SelectedIndices; foreach (int i in indices) { if (oldIndices.BinarySearch(i) >= 0) { mobFilter.CustomBattleIDs.Add(MobXPHandler.Instance.CompleteMobList.ElementAt(i).BattleID); } } foreach (int i in oldIndices) { if (!indices.Contains(i)) { mobFilter.CustomBattleIDs.Remove(MobXPHandler.Instance.CompleteMobList.ElementAt(i).BattleID); } } oldIndices = indices.Cast <int>().ToList <int>(); oldIndices.Sort(); UpdateFilter(); }
private void UpdateFilter() { var mobXPVals = MobXPHandler.Instance.CompleteMobList; MobFilter mobFilter = MobXPHandler.Instance.CustomMobFilter; mobFilter.CustomBattleIDs.Clear(); foreach (int index in mobList.SelectedIndices) { mobFilter.CustomBattleIDs.Add(mobXPVals.ElementAt(index).BattleID); } NotifyMobXPHandlerOfChangedMobList(); numMobsSelected.Text = mobList.SelectedIndices.Count.ToString(); }
private void ProcessOverall(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, ref StringBuilder sb, ref List <StringMods> strModList, out int numBattles, out TimeSpan totalFightsLength) { strModList.Add(new StringMods { Start = sb.Length, Length = lsOverallTitle.Length, Bold = true, Color = Color.Red }); sb.Append(lsOverallTitle + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsOverallHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsOverallHeader + "\n"); totalFightsLength = new TimeSpan(); foreach (var battleID in mobFilter.SelectedBattles) { totalFightsLength += dataSet.Battles.FindByBattleID(battleID).FightLength(); } numBattles = mobFilter.Count; sb.AppendFormat(lsOverallFormat, numBattles, totalFightsLength.FormattedShortTimeSpanString(false)); sb.Append("\n\n\n"); }
private void ProcessSetOfMobs(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter) { StringBuilder sb = new StringBuilder(); List <StringMods> strModList = new List <StringMods>(); int numBattles = 0; TimeSpan totalFightsLength; ProcessOverall(dataSet, attackSet, mobFilter, ref sb, ref strModList, out numBattles, out totalFightsLength); Dictionary <string, TimeSpan> playerCombatTime; ProcessParticipation(dataSet, attackSet, mobFilter, ref sb, ref strModList, numBattles, totalFightsLength, out playerCombatTime); ProcessDPM(dataSet, attackSet, mobFilter, ref sb, ref strModList, playerCombatTime); PushStrings(sb, strModList); }
private void ProcessCollectiveDamage(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, double[] xAxis) { DateTime startTime; DateTime endTime; GetTimeRange(attackSet, out startTime, out endTime); double[] sequenceDamage = GetCollectiveSequenceDamage(attackSet, startTime, endTime); string label = lsSequenceDamage; if (showCumulativeDamage) { sequenceDamage = AccumulateDamage(sequenceDamage); label = lsCumulativeDamage; } PointPairList ppl = new PointPairList(xAxis, sequenceDamage); zedGraphControl.GraphPane.AddCurve(label, ppl, Color.Red, SymbolType.None); zedGraphControl.AxisChange(); }
private void ProcessDPM(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, ref StringBuilder sb, ref List <StringMods> strModList, Dictionary <string, TimeSpan> playerCombatTime) { strModList.Add(new StringMods { Start = sb.Length, Length = lsDPSTitle.Length, Bold = true, Color = Color.Red }); sb.Append(lsDPSTitle + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsDPSHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsDPSHeader + "\n"); TimeSpan playerTimeFighting; foreach (var player in attackSet) { if (player.AnyAction.Any()) { playerTimeFighting = playerCombatTime[player.Name]; if (playerTimeFighting > TimeSpan.Zero) { int meleeDamage = player.MeleeDmg + player.MeleeEffectDmg; int rangeDamage = player.RangeDmg + player.RangeEffectDmg; int spellDamage = player.SpellDmg; int wsDamage = player.WSkillDmg; int otherDamage = player.AbilityDmg + player.CounterDmg + player.RetaliateDmg + player.SpikesDmg; int totalDamage = meleeDamage + rangeDamage + spellDamage + wsDamage + otherDamage; double meleeDPS = meleeDamage / playerTimeFighting.TotalSeconds; double rangeDPS = rangeDamage / playerTimeFighting.TotalSeconds; double spellDPS = spellDamage / playerTimeFighting.TotalSeconds; double wsDPS = wsDamage / playerTimeFighting.TotalSeconds; double otherDPS = otherDamage / playerTimeFighting.TotalSeconds; double totalDPS = totalDamage / playerTimeFighting.TotalSeconds; if (totalDamage > 0) { sb.AppendFormat(lsDPSFormat, player.DisplayName, meleeDPS, rangeDPS, wsDPS, spellDPS, otherDPS, totalDPS); sb.Append("\n"); } } } } }
private void ProcessParticipation(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, ref StringBuilder sb, ref List <StringMods> strModList, int numBattles, TimeSpan totalFightsLength, out Dictionary <string, TimeSpan> playerCombatTime) { strModList.Add(new StringMods { Start = sb.Length, Length = lsParticipateTitle.Length, Bold = true, Color = Color.Red }); sb.Append(lsParticipateTitle + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsParticipateFightsHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsParticipateFightsHeader + "\n"); Dictionary <string, int> playerFightCounts = new Dictionary <string, int>(); foreach (var player in attackSet) { int playerFightCount = 0; foreach (var fight in mobFilter.SelectedBattles) { if (player.AnyAction.Any(b => b.BattleID == fight)) { playerFightCount++; } } double participatingFights = (double)playerFightCount / numBattles; if (playerFightCount > 0) { playerFightCounts[player.Name] = playerFightCount; sb.AppendFormat(lsParticipateFightsFormat, player.DisplayName, playerFightCount, participatingFights); sb.Append("\n"); } } sb.Append("\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsParticipateTimeHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsParticipateTimeHeader + "\n"); playerCombatTime = new Dictionary <string, TimeSpan>(); foreach (var player in attackSet) { TimeSpan playerTimeFighting = new TimeSpan(); TimeSpan playerFightLengths = new TimeSpan(); foreach (var fight in mobFilter.SelectedBattles) { if (player.AnyAction.Any(b => b.BattleID == fight)) { var battle = dataSet.Battles.FindByBattleID(fight); playerFightLengths += battle.FightLength(); var firstAction = player.AnyAction.Where(b => b.BattleID == fight).FirstOrDefault(); var lastAction = player.AnyAction.Where(b => b.BattleID == fight).LastOrDefault(); // Assume 2 seconds to initiate first action of any fight. var timeSpentInFight = (lastAction.Timestamp - firstAction.Timestamp) + TimeSpan.FromSeconds(2); playerTimeFighting += timeSpentInFight; } } if (playerCombatTime.ContainsKey(player.Name)) { playerCombatTime[player.Name] += playerTimeFighting; } else { playerCombatTime[player.Name] = playerTimeFighting; } double percentFightsLength = playerTimeFighting.TotalSeconds / playerFightLengths.TotalSeconds; double percentOverallTime = playerTimeFighting.TotalSeconds / totalFightsLength.TotalSeconds; if (playerTimeFighting.TotalSeconds > 0) { double avgCombatTimePerFight = 0; int fights = 0; if (playerFightCounts.TryGetValue(player.Name, out fights)) { if (fights > 0) { avgCombatTimePerFight = playerTimeFighting.TotalSeconds / fights; } } sb.AppendFormat(lsParticipateTimeFormat, player.DisplayName, playerTimeFighting.FormattedShortTimeSpanString(false), playerFightLengths.FormattedShortTimeSpanString(false), FormatSeconds(avgCombatTimePerFight), percentFightsLength, percentOverallTime); sb.Append("\n"); } } sb.Append("\n\n"); }
private void ProcessFilteredMobs(KPDatabaseDataSet dataSet, string[] selectedPlayers, MobFilter mobFilter) { var attackSet = from c in dataSet.Combatants where (selectedPlayers.Contains(c.CombatantName)) orderby c.CombatantType, c.CombatantName let actorActions = c.GetInteractionsRowsByActorCombatantRelation() select new AttackGroup { Name = c.CombatantNameOrJobName, Melee = from n in actorActions where ((ActionType)n.ActionType == ActionType.Melee && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Heal) && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, Range = from n in actorActions where ((ActionType)n.ActionType == ActionType.Ranged && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Heal) && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, Spell = from n in actorActions where ((ActionType)n.ActionType == ActionType.Spell && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Heal) && n.Preparing == false && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, Ability = from n in actorActions where ((ActionType)n.ActionType == ActionType.Ability && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Unknown || (HarmType)n.HarmType == HarmType.Heal) && n.Preparing == false && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, WSkill = from n in actorActions where ((ActionType)n.ActionType == ActionType.Weaponskill && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Heal) && n.Preparing == false && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, SC = from n in actorActions where ((ActionType)n.ActionType == ActionType.Skillchain && ((HarmType)n.HarmType == HarmType.Damage || (HarmType)n.HarmType == HarmType.Drain || (HarmType)n.HarmType == HarmType.Heal) && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb)) && mobFilter.CheckFilterMobTarget(n) == true select n, Counter = from n in actorActions where (ActionType)n.ActionType == ActionType.Counterattack && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb) && mobFilter.CheckFilterMobTarget(n) == true select n, Retaliate = from n in actorActions where (ActionType)n.ActionType == ActionType.Retaliation && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb) && mobFilter.CheckFilterMobTarget(n) == true select n, Spikes = from n in actorActions where (ActionType)n.ActionType == ActionType.Spikes && ((DefenseType)n.DefenseType == DefenseType.None || (DefenseType)n.DefenseType == DefenseType.Absorb) && mobFilter.CheckFilterMobTarget(n) == true select n }; ProcessAttackSet(attackSet); }
private void ProcessSetOfMobs(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter) { StringBuilder sb = new StringBuilder(); List <StringMods> strModList = new List <StringMods>(); string meleeHeader = "Melee Effect # Procs # Hits Raw Proc % # Restricted Hits Restricted Proc %"; string rangeHeader = "Range Effect # Procs # Hits Raw Proc %"; string tmp = "Additional Effect Status Inflictions"; strModList.Add(new StringMods { Start = sb.Length, Length = tmp.Length, Bold = true, Color = Color.Red }); sb.Append(tmp + "\n\n"); foreach (var player in attackSet) { if ((player.Melee.Count() == 0) && (player.Range.Count() == 0)) { continue; } var meleeByAE = player.Melee.Where(a => a.IsSecondActionIDNull() == false && (HarmType)a.SecondHarmType == HarmType.Enfeeble); var rangeByAE = player.Range.Where(a => a.IsSecondActionIDNull() == false && (HarmType)a.SecondHarmType == HarmType.Enfeeble); if ((meleeByAE.Count() == 0) && (rangeByAE.Count() == 0)) { continue; } // Ok, this player has generated some AE effects. tmp = string.Format("{0}", player.DisplayName); strModList.Add(new StringMods { Start = sb.Length, Length = tmp.Length, Bold = true, Color = Color.Blue }); sb.Append(tmp + "\n\n"); int meleeCount = player.Melee.Count(); if (meleeCount > 0) { if (meleeByAE.Any()) { strModList.Add(new StringMods { Start = sb.Length, Length = meleeHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(meleeHeader + "\n"); var groupMeleeByAE = meleeByAE.GroupBy(a => a.ActionsRowBySecondaryActionNameRelation.ActionName); foreach (var ae in groupMeleeByAE) { var meleeAfterAE = player.Melee .Where(m => ae.Any(a => a.BattleID == m.BattleID && m.Timestamp >= a.Timestamp && m.Timestamp <= a.Timestamp.AddSeconds(30))); int countMeleeAfterAE = meleeAfterAE.Count(); int outsideMelee = meleeCount - countMeleeAfterAE; sb.AppendFormat("{0,-20}{1,10}{2,11}{3,15:p2}{4,21}{5,20:p2}\n", ae.Key, ae.Count(), meleeCount, (double)ae.Count() / meleeCount, outsideMelee, (outsideMelee > 0) ? (double)ae.Count() / outsideMelee : 0 ); } } } if (player.Range.Any()) { if (rangeByAE.Any()) { strModList.Add(new StringMods { Start = sb.Length, Length = rangeHeader.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(rangeHeader + "\n"); var groupRangeByAE = rangeByAE.GroupBy(a => a.ActionsRowBySecondaryActionNameRelation.ActionName); foreach (var ae in groupRangeByAE) { sb.AppendFormat("{0,-20}{1,10}{2,11}{3,15:p2}\n", ae.Key, ae.Count(), player.Range.Count(), (double)ae.Count() / player.Range.Count() ); } } } sb.Append("\n"); } PushStrings(sb, strModList); }
private void ProcessMobs(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { var allBattles = from b in dataSet.Battles where mobFilter.CheckFilterBattle(b) == true select b; // Actual killed mobs var battles = allBattles.Where(b => b.Killed == true); int battleCount = battles.Count(); string tmpStr = "Mobs"; strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Color = Color.Red }); sb.Append(tmpStr + "\n\n"); sb.AppendFormat("Total number of mobs: {0}\n\n", battles.Count()); if (battleCount > 0) { // Types of kills var dropDead = battles.Where(b => b.IsKillerIDNull() == true); var lastActions = from b in battles where b.IsKillerIDNull() == false select new { Battle = b, LastAction = GetLastAction(b) }; int meleeCount = 0; int magicCount = 0; int wsCount = 0; int jaCount = 0; int otherCount = 0; int dropDeadCount = 0; int unknownCount = 0; int petCount = 0; dropDeadCount = dropDead.Count(); foreach (var action in lastActions) { if (action.LastAction == null) { unknownCount++; } else { switch ((ActionType)action.LastAction.ActionType) { case ActionType.Ability: jaCount++; break; case ActionType.Spell: magicCount++; break; case ActionType.Weaponskill: case ActionType.Skillchain: wsCount++; break; case ActionType.Melee: case ActionType.Ranged: case ActionType.Counterattack: case ActionType.Retaliation: meleeCount++; break; default: otherCount++; break; } ; if ((EntityType)action.LastAction.CombatantsRowByActorCombatantRelation.CombatantType == EntityType.Pet) { petCount++; } } } tmpStr = "Kill Types:"; strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Color = Color.Black }); sb.Append(tmpStr + "\n\n"); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Melee", meleeCount, (double)meleeCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Magic", magicCount, (double)magicCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Weaponskill", wsCount, (double)wsCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Ability", jaCount, (double)jaCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Other", otherCount, (double)otherCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Drop dead", dropDeadCount, (double)dropDeadCount / battleCount); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Unknown", unknownCount, (double)unknownCount / battleCount); sb.Append("\n"); sb.AppendFormat("{0,-14}: {1,6} ({2,8:p2})\n", "Pets", petCount, (double)petCount / battleCount); sb.Append("\n\n"); // Cruor tmpStr = "Cruor:"; strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Color = Color.Black }); sb.Append(tmpStr + "\n\n"); var cruorBattles = battles.Where(b => b.GetLootRows().Any(l => l.ItemsRow.ItemName == lsCruor)); sb.AppendFormat("Number of mobs that dropped Cruor : {0}\n", cruorBattles.Count()); if (cruorBattles.Any()) { int totalCruor = cruorBattles.Sum(b => b.GetLootRows().First(l => l.ItemsRow.ItemName == lsCruor).GilDropped); double avgCruor = (double)totalCruor / cruorBattles.Count(); sb.AppendFormat("Total Cruor drop (mobs) : {0}\n", totalCruor); sb.AppendFormat("Average Cruor drop : {0:f2}\n", avgCruor); } sb.Append("\n\n"); } }
private void ProcessChests(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { string tmpStr = "Chests"; strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Color = Color.Red }); sb.Append(tmpStr + "\n\n"); var selectBattles = from b in dataSet.Battles where mobFilter.CheckFilterBattle(b) == true select b; var droppedChests = from b in selectBattles where b.GetLootRows().Any() && b.GetLootRows().Any(l => l.ItemsRow.ItemName == lsTreasureChest) select b; int droppedChestCount = droppedChests.Count(); var chestBattles = from b in dataSet.Battles where b.IsEnemyIDNull() == false && (EntityType)b.CombatantsRowByEnemyCombatantRelation.CombatantType == EntityType.TreasureChest select b; int failedChests = 0; int expiredChests = 0; int openedChests = 0; int usedKey = 0; int chestsWithCruor = 0; int cruorTotal = 0; int chestsWithExperience = 0; int experienceTotal = 0; int chestsWithTE = 0; foreach (var chestBattle in chestBattles) { if (chestBattle.Killed) { openedChests++; if (chestBattle.GetInteractionsRows() .Any(i => i.IsItemIDNull() == false && i.ItemsRow.ItemName == lsKey)) { usedKey++; } if (chestBattle.ExperiencePoints > 0) { chestsWithExperience++; experienceTotal += chestBattle.ExperiencePoints; } else { var chestLoot = chestBattle.GetLootRows(); if (chestLoot.Any()) { var cruorLoot = chestLoot.Where(l => l.ItemsRow.ItemName == lsCruor); if ((cruorLoot != null) && (cruorLoot.Any())) { chestsWithCruor++; cruorTotal += cruorLoot.Sum(l => l.GilDropped); } var teLoot = chestLoot.Where(l => l.ItemsRow.ItemName == lsTimeExtension); if ((teLoot != null) && (teLoot.Any())) { chestsWithTE++; } } } } else { if (chestBattle.GetInteractionsRows() .Any(i => (FailedActionType)i.FailedActionType == FailedActionType.FailedUnlock)) { failedChests++; } else { expiredChests++; } } } if (droppedChestCount + failedChests + openedChests > 0) { sb.AppendFormat("Dropped chests : {0}\n", droppedChestCount); sb.AppendFormat("Expired chests : {0}\n", expiredChests); sb.AppendFormat("Failed chests : {0}\n", failedChests); sb.Append("\n"); sb.AppendFormat("Opened chests : {0}\n", openedChests); sb.AppendFormat(" - Using a key : {0}\n", usedKey); sb.Append("\n"); if (chestsWithTE > 0) { sb.AppendFormat("Chests that granted Time Extensions : {0}\n", chestsWithTE); sb.AppendFormat(" - Total time gained : {0}\n", new TimeSpan(0, chestsWithTE * 10, 0).FormattedShortTimeSpanString()); sb.Append("\n"); } if (chestsWithExperience > 0) { sb.AppendFormat("Chests that granted experience : {0}\n", chestsWithExperience); sb.AppendFormat(" - Total experience : {0}\n", experienceTotal); sb.AppendFormat(" - Average experience : {0:f2}\n", (double)experienceTotal / chestsWithExperience); sb.Append("\n"); } if (chestsWithCruor > 0) { sb.AppendFormat("Chests that granted Cruor : {0}\n", chestsWithCruor); sb.AppendFormat(" - Total Cruor : {0}\n", cruorTotal); sb.AppendFormat(" - Average Cruor : {0:f2}\n", (double)cruorTotal / chestsWithCruor); } sb.Append("\n\n"); } }
private void ProcessSingleIndividualDamage(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, double[] xAxis) { DateTime startTime; DateTime endTime; GetTimeRange(attackSet, out startTime, out endTime); int colorIndex = 0; foreach (var player in attackSet) { if (player.AnyAction.Any()) { double[] playerDamage = GetIndividualSequenceDamage(player, startTime, endTime); string label = player.DisplayName; string buffName = buffsCombo.CBSelectedItem(); if (showCumulativeDamage) { playerDamage = AccumulateDamage(playerDamage); } if (buffName != lsNone) { var intervals = CollectTimeIntervals.GetTimeIntervals(dataSet, new List <string>() { player.Name }); var playerIntervals = intervals.FirstOrDefault(i => i.PlayerName == player.Name); if (playerIntervals != null) { var actionIntervals = playerIntervals.TimeIntervalSets.FirstOrDefault( i => i.SetName == buffName); if ((actionIntervals != null) && (actionIntervals.TimeIntervals.Count > 0)) { //double[] playerInDamage = new double[playerDamage.Length]; double[] playerOutDamage = new double[playerDamage.Length]; DateTime timePoint; for (int i = 0; i < playerDamage.Length; i++) { timePoint = startTime.AddSeconds(i * xAxisScale); if (!actionIntervals.Contains(timePoint)) { // playerInDamage[i] = playerDamage[i]; //else playerOutDamage[i] = playerDamage[i]; } } string label1 = label + " w/" + buffName; string label2 = label + " wo/" + buffName; PointPairList ppl2 = new PointPairList(xAxis, playerOutDamage); var li2 = zedGraphControl.GraphPane.AddCurve(label2, ppl2, Color.Red, SymbolType.None); li2.Line.Fill = new Fill(Color.Red, Color.Bisque); PointPairList ppl1 = new PointPairList(xAxis, playerDamage); var li1 = zedGraphControl.GraphPane.AddCurve(label1, ppl1, Color.Blue, SymbolType.None); li1.Line.Fill = new Fill(Color.Blue, Color.LightBlue); continue; } } } else { PointPairList ppl = new PointPairList(xAxis, playerDamage); zedGraphControl.GraphPane.AddCurve(label, ppl, indexOfColors[colorIndex], SymbolType.None); colorIndex = (colorIndex + 1) % 18; } } } zedGraphControl.AxisChange(); }
private void ProcessLights(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { string tmpStr = "Lights"; strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Color = Color.Red }); sb.Append(tmpStr + "\n\n"); var allBattles = from b in dataSet.Battles where mobFilter.CheckFilterBattle(b) == true || (b.IsEnemyIDNull() == false && (EntityType)b.CombatantsRowByEnemyCombatantRelation.CombatantType == EntityType.TreasureChest) select b; var lightRewards = from b in allBattles let loot = b.GetLootRows() let light = loot.FirstOrDefault(l => colorLight.Match(l.ItemsRow.ItemName).Success == true) where light != null group b by light.ItemsRow.ItemName; // Header string formatString = "{0,-18} : {1,10}{2,14}{3,10}"; tmpStr = string.Format(formatString, "Color Light", "From Mobs", "From Chests", "Total"); strModList.Add(new StringMods { Start = sb.Length, Length = tmpStr.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(tmpStr + "\n"); int totalMobCount = 0; int totalChestCount = 0; int totalCount = 0; foreach (var light in lightRewards.OrderBy(a => a.Key)) { int lightCount = light.Count(); int chestLightCount = light.Count(a => (EntityType)a.CombatantsRowByEnemyCombatantRelation.CombatantType == EntityType.TreasureChest); int mobLightCount = lightCount - chestLightCount; totalCount += lightCount; totalMobCount += mobLightCount; totalChestCount += chestLightCount; sb.AppendFormat(formatString, light.Key, mobLightCount, chestLightCount, lightCount); sb.Append("\n"); } if (totalCount > 0) { sb.Append("\n"); sb.AppendFormat(formatString, "Total", totalMobCount, totalChestCount, totalCount); sb.Append("\n"); } sb.Append("\n\n"); }
private void DoProcessWork(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { throw new NotImplementedException(); }
private void ProcessIndividualDamage(KPDatabaseDataSet dataSet, EnumerableRowCollection <AttackGroup> attackSet, MobFilter mobFilter, double[] xAxis) { DateTime startTime; DateTime endTime; GetTimeRange(attackSet, out startTime, out endTime); int colorIndex = 0; foreach (var player in attackSet) { if (player.AnyAction.Any()) { double[] playerDamage = GetIndividualSequenceDamage(player, startTime, endTime); string label = player.DisplayName; if (showCumulativeDamage) { playerDamage = AccumulateDamage(playerDamage); } PointPairList ppl = new PointPairList(xAxis, playerDamage); zedGraphControl.GraphPane.AddCurve(label, ppl, indexOfColors[colorIndex], SymbolType.None); colorIndex = (colorIndex + 1) % 18; } } zedGraphControl.AxisChange(); }
/// <summary> /// An extension method to determine whether a given InteractionsRow passes the filter /// check set by the specified MobFilter object. Checks the filter against the target /// of the action. /// </summary> /// <param name="mobFilter">The filter to check against.</param> /// <param name="rowToCheck">The InteractionsRow to check.</param> /// <returns>Returns true if the row passes the filter test, otherwise false.</returns> public static bool CheckFilterBattle(this MobFilter mobFilter, KPDatabaseDataSet.BattlesRow rowToCheck) { if (mobFilter.AllMobs == true) { if (mobFilter.Exclude0XPMobs) { return(rowToCheck.ExperiencePoints > 0); } else if (rowToCheck.IsEnemyIDNull() == true) { return(false); } else if ((EntityType)rowToCheck.CombatantsRowByEnemyCombatantRelation.CombatantType == EntityType.Mob) { return(true); } } if (rowToCheck.DefaultBattle == true) { return(false); } if (mobFilter.CustomSelection == true) { return(mobFilter.CustomBattleIDs.Contains(rowToCheck.BattleID)); } if (mobFilter.GroupMobs == false) { if (rowToCheck.BattleID == mobFilter.FightNumber) { return(true); } else { return(false); } } if (mobFilter.MobName == string.Empty) { return(false); } if (rowToCheck.IsEnemyIDNull() == true) { return(false); } if ((EntityType)rowToCheck.CombatantsRowByEnemyCombatantRelation.CombatantType != EntityType.Mob) { return(false); } if (rowToCheck.CombatantsRowByEnemyCombatantRelation.CombatantName == mobFilter.MobName) { if (mobFilter.MobXP == -1) { return(true); } if (mobFilter.MobXP == MobXPHandler.Instance.GetBaseXP(rowToCheck.BattleID)) { return(true); } } return(false); }
/// <summary> /// An extension method to determine whether a given InteractionsRow passes the filter /// check set by the specified MobFilter object. Checks the filter against the battle /// during which the action occurs /// </summary> /// <param name="mobFilter">The filter to check against.</param> /// <param name="rowToCheck">The InteractionsRow to check.</param> /// <returns>Returns true if the row passes the filter test, otherwise false.</returns> public static bool CheckFilterMobBattle(this MobFilter mobFilter, KPDatabaseDataSet.InteractionsRow rowToCheck) { if (mobFilter.AllMobs == true) { // If no battle attached, include it as "between battles" actions; valid if (rowToCheck.IsBattleIDNull() == true) { return(true); } if (mobFilter.Exclude0XPMobs) { return(rowToCheck.BattlesRow.ExperiencePoints > 0); } else { return(true); } } if (mobFilter.CustomSelection == true) { if (rowToCheck.IsBattleIDNull() == true) { return(false); } return(mobFilter.CustomBattleIDs.Contains(rowToCheck.BattleID)); } if (mobFilter.GroupMobs == false) { if ((rowToCheck.IsBattleIDNull() == false) && (rowToCheck.BattleID == mobFilter.FightNumber)) { return(true); } else { return(false); } } if (mobFilter.MobName == string.Empty) { return(false); } if (rowToCheck.IsBattleIDNull() == true) { return(false); } if (rowToCheck.BattlesRow.IsEnemyIDNull() == true) { return(false); } if (rowToCheck.BattlesRow.CombatantsRowByEnemyCombatantRelation.CombatantName == mobFilter.MobName) { if (mobFilter.MobXP == -1) { return(true); } if (mobFilter.MobXP == MobXPHandler.Instance.GetBaseXP(rowToCheck.BattleID)) { return(true); } } return(false); }
private void ProcessDamage(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { var playerData = from c in dataSet.Combatants where (((EntityType)c.CombatantType == EntityType.Player) || ((EntityType)c.CombatantType == EntityType.Pet) || ((EntityType)c.CombatantType == EntityType.CharmedMob) || ((EntityType)c.CombatantType == EntityType.Fellow)) orderby c.CombatantType, c.CombatantName let targetInteractions = c.GetInteractionsRowsByTargetCombatantRelation().Where(a => mobFilter.CheckFilterMobBattle(a)) let actorInteractions = c.GetInteractionsRowsByActorCombatantRelation().Where(a => mobFilter.CheckFilterMobBattle(a)) select new { Player = c.CombatantNameOrJobName, PrimeDmgTaken = from dm in targetInteractions where (((HarmType)dm.HarmType == HarmType.Damage) || ((HarmType)dm.HarmType == HarmType.Drain)) select dm.Amount, SecondDmgTaken = from dm in targetInteractions where (((HarmType)dm.SecondHarmType == HarmType.Damage) || ((HarmType)dm.SecondHarmType == HarmType.Drain)) select dm.SecondAmount, PrimeDrain = from dr in actorInteractions where ((HarmType)dr.HarmType == HarmType.Drain) && mobFilter.CheckFilterMobBattle(dr) select dr.Amount, SecondDrain = from dr in actorInteractions where (((HarmType)dr.SecondHarmType == HarmType.Drain) || ((AidType)dr.SecondAidType == AidType.Recovery)) select dr.SecondAmount, Cured = from cr in targetInteractions where (((AidType)cr.AidType == AidType.Recovery) && ((RecoveryType)cr.RecoveryType == RecoveryType.RecoverHP)) select cr.Amount, Regen1 = from cr in targetInteractions where (((AidType)cr.AidType == AidType.Enhance) && (cr.IsActionIDNull() == false) && (cr.ActionsRow.ActionName == lsRegen1)) select cr, Regen2 = from cr in targetInteractions where (((AidType)cr.AidType == AidType.Enhance) && (cr.IsActionIDNull() == false) && (cr.ActionsRow.ActionName == lsRegen2)) select cr, Regen3 = from cr in targetInteractions where (((AidType)cr.AidType == AidType.Enhance) && (cr.IsActionIDNull() == false) && (cr.ActionsRow.ActionName == lsRegen3)) select cr, Regen4 = from cr in targetInteractions where (((AidType)cr.AidType == AidType.Enhance) && (cr.IsActionIDNull() == false) && (cr.ActionsRow.ActionName == lsRegen4)) select cr, }; int dmgTaken = 0; int drainAmt = 0; int healAmt = 0; int numR1 = 0; int numR2 = 0; int numR3 = 0; int numR4 = 0; int ttlDmgTaken = 0; int ttlDrainAmt = 0; int ttlHealAmt = 0; int ttlNumR1 = 0; int ttlNumR2 = 0; int ttlNumR3 = 0; int ttlNumR4 = 0; bool placeHeader = false; if (playerData.Any()) { foreach (var player in playerData) { dmgTaken = player.PrimeDmgTaken.Sum() + player.SecondDmgTaken.Sum(); drainAmt = player.PrimeDrain.Sum() + player.SecondDrain.Sum(); healAmt = player.Cured.Sum(); numR1 = player.Regen1.Count(); numR2 = player.Regen2.Count(); numR3 = player.Regen3.Count(); numR4 = player.Regen4.Count(); if ((dmgTaken + drainAmt + healAmt + numR1 + numR2 + numR3 + numR4) > 0) { if (placeHeader == false) { strModList.Add(new StringMods { Start = sb.Length, Length = lsTitleRecovery.Length, Bold = true, Color = Color.Red }); sb.Append(lsTitleRecovery + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsHeaderRecovery.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsHeaderRecovery + "\n"); placeHeader = true; } ttlDmgTaken += dmgTaken; ttlDrainAmt += drainAmt; ttlHealAmt += healAmt; ttlNumR1 += numR1; ttlNumR2 += numR2; ttlNumR3 += numR3; ttlNumR4 += numR4; sb.AppendFormat(lsFormatRecovery, player.Player, dmgTaken, drainAmt, healAmt, numR1, numR2, numR3, numR4); sb.Append("\n"); } } if (placeHeader == true) { string totalString = string.Format(lsFormatRecovery, lsTotal, ttlDmgTaken, ttlDrainAmt, ttlHealAmt, ttlNumR1, ttlNumR2, ttlNumR3, ttlNumR4); strModList.Add(new StringMods { Start = sb.Length, Length = totalString.Length, Bold = true, Color = Color.Black }); sb.Append(totalString + "\n\n\n"); } } }
private void ProcessStatusCured(KPDatabaseDataSet dataSet, MobFilter mobFilter, ref StringBuilder sb, List <StringMods> strModList) { var statusHealing = from c in dataSet.Combatants where (((EntityType)c.CombatantType == EntityType.Player) || ((EntityType)c.CombatantType == EntityType.Pet) || ((EntityType)c.CombatantType == EntityType.Fellow)) orderby c.CombatantType, c.CombatantName let targetInteractions = c.GetInteractionsRowsByTargetCombatantRelation().Where(a => mobFilter.CheckFilterMobBattle(a)) select new { Player = c.CombatantNameOrJobName, StatusRemovals = from cr in targetInteractions where ((AidType)cr.AidType == AidType.RemoveStatus) && (cr.IsActionIDNull() == false) group cr by cr.ActionsRow.ActionName }; bool placeHeader = false; foreach (var player in statusHealing) { if (player.StatusRemovals.Any()) { if (placeHeader == false) { strModList.Add(new StringMods { Start = sb.Length, Length = lsTitleStatusCured.Length, Bold = true, Color = Color.Red }); sb.Append(lsTitleStatusCured + "\n\n"); placeHeader = true; } strModList.Add(new StringMods { Start = sb.Length, Length = player.Player.Length, Bold = true, Color = Color.Blue }); sb.Append(player.Player + "\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsHeaderStatusCuring.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsHeaderStatusCuring + "\n"); foreach (var statusSpell in player.StatusRemovals) { int spellUsed = statusSpell.Count(); int spellNoEffect = statusSpell.Count(a => (FailedActionType)a.FailedActionType == FailedActionType.NoEffect); sb.AppendFormat(lsFormatStatusCuring, statusSpell.Key, spellUsed, spellNoEffect); sb.Append("\n"); var effects = statusSpell.GroupBy(a => a.IsSecondActionIDNull() ? "-unknown-" : a.ActionsRowBySecondaryActionNameRelation.ActionName); foreach (var effect in effects) { if (effect.Key != "-unknown-") { sb.AppendFormat(lsFormatStatusCuringSub, effect.Key, effect.Count()); sb.Append("\n"); } } } sb.Append("\n"); } } }
private void ProcessCuring(KPDatabaseDataSet dataSet, MobFilter mobFilter, bool displayCures, bool displayAvgCures, ref StringBuilder sb, List <StringMods> strModList) { // linq query to get the basic rows with healing var uberHealing = from c in dataSet.Combatants where (((EntityType)c.CombatantType == EntityType.Player) || ((EntityType)c.CombatantType == EntityType.Pet) || ((EntityType)c.CombatantType == EntityType.Fellow)) orderby c.CombatantType, c.CombatantName select new { Player = c.CombatantNameOrJobName, Healing = from h in c.GetInteractionsRowsByActorCombatantRelation() where mobFilter.CheckFilterMobBattle(h) && h.IsActionIDNull() == false && ((AidType)h.AidType == AidType.Recovery || (AidType)h.AidType == AidType.Enhance) select h }; int cureSpell = 0; int cureAbil = 0; int numCure1 = 0; int numCure2 = 0; int numCure3 = 0; int numCure4 = 0; int numCure5 = 0; int numCure6 = 0; int numCuraga = 0; int numRegen1 = 0; int numRegen2 = 0; int numRegen3 = 0; int numRegen4 = 0; double avgC1 = 0; double avgC2 = 0; double avgC3 = 0; double avgC4 = 0; double avgC5 = 0; double avgC6 = 0; double avgCg = 0; double avgAb = 0; bool placeHeader = false; if (uberHealing.Any()) { if (displayCures == true) { StringBuilder costsSB2 = new StringBuilder(); foreach (var healer in uberHealing) { var healLU = healer.Healing.ToLookup(a => a.ActionsRow.ActionName); numCure1 = healLU[lsCure1].Count() + healLU[lsPollen].Count() + healLU[lsHealingBreath1].Count(); numCure2 = healLU[lsCure2].Count() + healLU[lsCWaltz1].Count() + healLU[lsHealingBreath2].Count(); numCure3 = healLU[lsCure3].Count() + healLU[lsCWaltz2].Count() + healLU[lsHealingBreath3].Count() + healLU[lsWildCarrot].Count(); numCure4 = healLU[lsCure4].Count() + healLU[lsCWaltz3].Count() + healLU[lsMagicFruit].Count(); numCure5 = healLU[lsCure5].Count() + healLU[lsCWaltz4].Count(); numCure6 = healLU[lsCure6].Count() + healLU[lsCWaltz5].Count(); numCuraga = healLU[lsHealingBreeze].GroupBy(a => a.Timestamp).Count() + healLU[lsDivineWaltz1].GroupBy(a => a.Timestamp).Count() + healLU[lsDivineWaltz2].GroupBy(a => a.Timestamp).Count() + healLU[lsCura1].GroupBy(a => a.Timestamp).Count() + healLU[lsCura2].GroupBy(a => a.Timestamp).Count() + healLU[lsCuraga1].GroupBy(a => a.Timestamp).Count() + healLU[lsCuraga2].GroupBy(a => a.Timestamp).Count() + healLU[lsCuraga3].GroupBy(a => a.Timestamp).Count() + healLU[lsCuraga4].GroupBy(a => a.Timestamp).Count(); numRegen1 = healLU[lsRegen1].Count(); numRegen2 = healLU[lsRegen2].Count(); numRegen3 = healLU[lsRegen3].Count(); numRegen4 = healLU[lsRegen4].Count(); var cures = healer.Healing.Where(a => (AidType)a.AidType == AidType.Recovery && (RecoveryType)a.RecoveryType == RecoveryType.RecoverHP); var spellCures = cures.Where(a => (ActionType)a.ActionType == ActionType.Spell); var abilCures = cures.Where(a => (ActionType)a.ActionType == ActionType.Ability); cureSpell = spellCures.Sum(a => a.Amount); cureAbil = abilCures.Sum(a => a.Amount); if ((cureSpell + cureAbil + numCure1 + numCure2 + numCure3 + numCure4 + numCure5 + numCure6 + numRegen1 + numRegen2 + numRegen3 + numRegen4 + numCuraga) > 0) { if (placeHeader == false) { strModList.Add(new StringMods { Start = sb.Length, Length = lsTitleCuring.Length, Bold = true, Color = Color.Red }); sb.Append(lsTitleCuring + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsHeaderCuring.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsHeaderCuring + "\n"); placeHeader = true; } sb.AppendFormat(lsFormatCuring, healer.Player, cureSpell, cureAbil, numCure1, numCure2, numCure3, numCure4, numCure5, numCure6, numCuraga, numRegen1, numRegen2, numRegen3, numRegen4); sb.Append("\n"); // Costs of curing (generate text for this during this loop) int totalMP = 0; totalMP += healLU[lsCure1].Count() * 8; totalMP += healLU[lsCure2].Count() * 24; totalMP += healLU[lsCure3].Count() * 46; totalMP += healLU[lsCure4].Count() * 88; totalMP += healLU[lsCure5].Count() * 135; totalMP += healLU[lsCure6].Count() * 227; totalMP += healLU[lsPollen].Count() * 8; totalMP += healLU[lsWildCarrot].Count() * 37; totalMP += healLU[lsMagicFruit].Count() * 72; totalMP += healLU[lsHealingBreeze].Count() * 55; totalMP += healLU[lsCura1].Count() * 30; totalMP += healLU[lsCura2].Count() * 60; totalMP += healLU[lsCuraga1].GroupBy(a => a.Timestamp).Count() * 60; totalMP += healLU[lsCuraga2].GroupBy(a => a.Timestamp).Count() * 120; totalMP += healLU[lsCuraga3].GroupBy(a => a.Timestamp).Count() * 180; totalMP += healLU[lsCuraga4].GroupBy(a => a.Timestamp).Count() * 260; int regenCost = 0; regenCost += numRegen1 * 15; regenCost += numRegen2 * 36; regenCost += numRegen3 * 64; regenCost += numRegen4 * 82; totalMP += regenCost; int totalTP = 0; totalTP += healLU[lsCWaltz1].Count() * 20; totalTP += healLU[lsCWaltz2].Count() * 35; totalTP += healLU[lsCWaltz3].Count() * 50; totalTP += healLU[lsCWaltz4].Count() * 65; totalTP += healLU[lsCWaltz5].Count() * 80; totalTP += healLU[lsDivineWaltz1].Count() * 40; totalTP += healLU[lsDivineWaltz2].Count() * 80; float mpCureEff = 0; float mpCureRegEff = 0; float tpCureEff = 0; if (totalMP > 0) { if (totalMP > regenCost) { mpCureEff = (float)cureSpell / (totalMP - regenCost); } else { mpCureEff = 0; } int curesWithRegen = cureSpell + numRegen1 * 125 + numRegen2 * 240 + numRegen3 * 400 + numRegen4 * 600; mpCureRegEff = (float)curesWithRegen / totalMP; } if (totalTP > 0) { int tpCures = cureAbil - healLU[lsChakra].Sum(a => a.Amount); tpCureEff = (float)tpCures / totalTP; } if ((totalMP > 0) || (totalTP > 0)) { costsSB2.AppendFormat(lsFormatCuringCost, healer.Player, totalMP, mpCureEff, mpCureRegEff, totalTP, tpCureEff); costsSB2.Append("\n"); } } } // Insert costs calculations into the text stream here if (placeHeader) { sb.Append("\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsTitleCuringCost.Length, Bold = true, Color = Color.Blue }); sb.Append(lsTitleCuringCost + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsHeaderCuringCost.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsHeaderCuringCost + "\n"); sb.Append(costsSB2.ToString()); sb.Append("\n\n"); } } if (displayAvgCures == true) { placeHeader = false; foreach (var healer in uberHealing) { var healLU = healer.Healing.ToLookup(a => a.ActionsRow.ActionName); avgCg = 0; avgAb = 0; avgC1 = healLU[lsCure1].Concat(healLU[lsPollen]).Concat(healLU[lsHealingBreath1]) .Average(a => (int?)a.Amount) ?? 0.0; avgC2 = healLU[lsCure2].Concat(healLU[lsHealingBreath2]).Concat(healLU[lsCWaltz1]) .Average(a => (int?)a.Amount) ?? 0.0; avgC3 = healLU[lsCure3].Concat(healLU[lsHealingBreath3]).Concat(healLU[lsCWaltz2]).Concat(healLU[lsWildCarrot]) .Average(a => (int?)a.Amount) ?? 0.0; avgC4 = healLU[lsCure4].Concat(healLU[lsMagicFruit]).Concat(healLU[lsCWaltz3]) .Average(a => (int?)a.Amount) ?? 0.0; avgC5 = healLU[lsCure5].Concat(healLU[lsCWaltz4]) .Average(a => (int?)a.Amount) ?? 0.0; avgC6 = healLU[lsCure6].Average(a => (int?)a.Amount) ?? 0.0; avgCg = healLU[lsCura1].GroupBy(a => a.Timestamp) .Concat(healLU[lsCura2].GroupBy(a => a.Timestamp)) .Concat(healLU[lsCuraga1].GroupBy(a => a.Timestamp)) .Concat(healLU[lsCuraga2].GroupBy(a => a.Timestamp)) .Concat(healLU[lsCuraga3].GroupBy(a => a.Timestamp)) .Concat(healLU[lsCuraga4].GroupBy(a => a.Timestamp)) .Concat(healLU[lsDivineWaltz1].GroupBy(a => a.Timestamp)) .Concat(healLU[lsDivineWaltz2].GroupBy(a => a.Timestamp)) .Concat(healLU[lsHealingBreeze].GroupBy(a => a.Timestamp)) .Average(a => a.Sum(b => (int?)b.Amount)) ?? 0.0; avgAb = healLU[lsChakra] .Average(a => (int?)a.Amount) ?? 0.0; if ((avgAb + avgC1 + avgC2 + avgC3 + avgC4 + avgC5 + avgC6 + avgCg) > 0) { if (placeHeader == false) { strModList.Add(new StringMods { Start = sb.Length, Length = lsTitleAvgCuring.Length, Bold = true, Color = Color.Red }); sb.Append(lsTitleAvgCuring + "\n\n"); strModList.Add(new StringMods { Start = sb.Length, Length = lsHeaderAvgCuring.Length, Bold = true, Underline = true, Color = Color.Black }); sb.Append(lsHeaderAvgCuring + "\n"); placeHeader = true; } sb.AppendFormat(lsFormatAvgCuring, healer.Player, avgC1, avgC2, avgC3, avgC4, avgC5, avgC6, avgCg, avgAb); sb.Append("\n"); } } if (placeHeader) { sb.Append("\n\n"); } } } }