public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;

            StatsMoonkin statsTotal = new StatsMoonkin();
            Stats statsBase = BaseStats.GetBaseStats(character.Level, character.Class, character.Race, BaseStats.DruidForm.Moonkin);
            statsTotal.Accumulate(statsBase);
            
            // Get the gear/enchants/buffs stats loaded in
            statsTotal.Accumulate(GetItemStats(character, additionalItem));
            statsTotal.Accumulate(GetBuffsStats(character, calcOpts));

            #region Set Bonuses
            int T11Count, T12Count, T13Count;
            character.SetBonusCount.TryGetValue("Stormrider's Regalia", out T11Count);
            character.SetBonusCount.TryGetValue("Obsidian Arborweave Regalia", out T12Count);
            character.SetBonusCount.TryGetValue("Deep Earth Regalia", out T13Count);
            if (T11Count >= 2) {
                // 2 pieces: Increases the critical strike chance of your Insect Swarm and Moonfire spells by 5%.
                statsTotal.BonusCritChanceInsectSwarm = 0.05f;
                statsTotal.BonusCritChanceMoonfire = 0.05f;
            }
            if (T11Count >= 4) {
                // 4 pieces: Whenever Eclipse triggers, your critical strike chance with spells is increased by 99%
                //           for 8 sec. Each critical strike you achieve reduces that bonus by 33%.
                // 4.2: 15% for 8 seconds, bonus reduced by 5% per crit.
                statsTotal.AddSpecialEffect(_SE_T114P);
            }
            if (T12Count >= 2)
            {
                // 2 piece: You have a (20%) chance to summon a Burning Treant when you cast Wrath or Starfire.
                statsTotal.AddSpecialEffect(_SE_T122P);
            }
            if (T12Count >= 4)
            {
                // 4 piece: Your Wrath generates +3 and your Starfire generates +5 energy when not in Eclipse.
                statsTotal.BonusWrathEnergy = 3f + 1/3f;
                statsTotal.BonusStarfireEnergy = 5f;
            }
            if (T13Count >= 2)
            {
                // 2 piece: Your nukes deal 3% more damage when Insect Swarm is active on the target.
                statsTotal.BonusNukeDamageModifier = 0.03f;
            }
            if (T13Count >= 4)
            {
                // 4 piece: Your Starsurge generates +100% Lunar or Solar energy when not in Eclipse.
                statsTotal.T13FourPieceActive = true;
            }
            #endregion

            // Talented bonus multipliers
            Stats statsTalents = new StatsMoonkin()
            {
                BonusIntellectMultiplier = (1 + 0.02f * character.DruidTalents.HeartOfTheWild) * (Character.ValidateArmorSpecialization(character, ItemType.Leather) ? 1.05f : 1f) - 1f,
                BonusManaMultiplier = 0.05f * character.DruidTalents.Furor
            };
            statsTotal.BonusSpellDamageMultiplier = (1 + 0.01f * character.DruidTalents.BalanceOfPower) * (1 + 0.02f * character.DruidTalents.EarthAndMoon) *
                                            (1 + 0.1f * character.DruidTalents.MoonkinForm) *
                                            (1 + (character.DruidTalents.MoonkinForm > 0 ? 0.04f * character.DruidTalents.MasterShapeshifter : 0.0f)) - 1;

            statsTotal.Accumulate(statsTalents);

            // Base stats: Intellect, Stamina, Spirit, Agility
            statsTotal.Stamina = (float)Math.Floor(statsTotal.Stamina * (1 + statsTotal.BonusStaminaMultiplier));
            statsTotal.Intellect = (float)Math.Floor(statsTotal.Intellect * (1 + statsTotal.BonusIntellectMultiplier));
            statsTotal.Agility = (float)Math.Floor(statsTotal.Agility * (1 + statsTotal.BonusAgilityMultiplier));
            statsTotal.Spirit = (float)Math.Floor(statsTotal.Spirit * (1 + statsTotal.BonusSpiritMultiplier));

            // Derived stats: Health, mana pool, armor
            statsTotal.Health = (float)Math.Round(statsTotal.Health + StatConversion.GetHealthFromStamina(statsTotal.Stamina));
            statsTotal.Health = (float)Math.Floor(statsTotal.Health * (1f + statsTotal.BonusHealthMultiplier));
            statsTotal.Mana = (float)Math.Round(statsTotal.Mana + StatConversion.GetManaFromIntellect(statsTotal.Intellect));
            statsTotal.Mana = (float)Math.Floor(statsTotal.Mana * (1f + statsTotal.BonusManaMultiplier));
            // Armor
            statsTotal.Armor = statsTotal.Armor * (1f + statsTotal.BaseArmorMultiplier);
            statsTotal.BonusArmor = statsTotal.BonusArmor * (1f + statsTotal.BonusArmorMultiplier);
            statsTotal.Armor += statsTotal.BonusArmor;
            statsTotal.Armor = (float)Math.Round(statsTotal.Armor);

            // Crit rating
            // Application order: Stats, Talents, Gear
            // All spells: Crit% + (0.02 * Nature's Majesty)
            statsTotal.SpellCrit += 0.02f * character.DruidTalents.NaturesMajesty;
            // All spells: Hit rating + 0.5f * Balance of Power * Spirit
            statsTotal.HitRating += 0.5f * character.DruidTalents.BalanceOfPower * (statsTotal.Spirit - statsBase.Spirit);

            return statsTotal;
        }
        public override Dictionary<string, string> GetCharacterDisplayCalculationValues() {
            Dictionary<string, string> retVal = new Dictionary<string, string>();
            //
            if (baseStats == null) baseStats = new StatsMoonkin();
            if (SelectedRotation == null) SelectedRotation = new RotationData();
            if (BurstRotation == null) BurstRotation = new RotationData();
            //
            retVal.Add("Health", baseStats.Health.ToString());
            retVal.Add("Mana", baseStats.Mana.ToString());
            retVal.Add("Armor", baseStats.Armor.ToString());
            retVal.Add("Agility", baseStats.Agility.ToString());
            retVal.Add("Stamina", baseStats.Stamina.ToString());
            retVal.Add("Intellect", baseStats.Intellect.ToString());
            retVal.Add("Spirit", baseStats.Spirit.ToString());
            retVal.Add("Spell Power", SpellPower.ToString());

            float totalHitDelta = SpellHitCap - SpellHit;

            retVal.Add("Spell Hit", String.Format("{0:F}%*{1} Hit Rating, {2:F}% Hit From Gear" + (totalHitDelta != 0 ? ", {3} Rating {4}" : ""),
                100 * SpellHit,
                baseStats.HitRating,
                100 * StatConversion.GetSpellHitFromRating(baseStats.HitRating),
                StatConversion.GetRatingFromHit(Math.Abs(totalHitDelta)),
                totalHitDelta > 0 ? "To Cap" : "Over Cap"));
            retVal.Add("Spell Crit", String.Format("{0:F}%*{1} Crit Rating, {2:F}% Crit From Gear, {3:F}% Crit From Intellect",
                100 * SpellCrit,
                baseStats.CritRating,
                100 * StatConversion.GetSpellCritFromRating(baseStats.CritRating),
                100 * StatConversion.GetSpellCritFromIntellect(baseStats.Intellect)));
            retVal.Add("Spell Haste", String.Format("{0:F}%*{1} Haste Rating, {2:F}% Haste From Gear",
                100 * SpellHaste,
                baseStats.HasteRating,
                100 * StatConversion.GetSpellHasteFromRating(baseStats.HasteRating)));
            retVal.Add("Mastery", String.Format("{0:F}*{1:F} Eclipse %, {2} Rating",
                Mastery,
                Mastery * 2.0f,
                baseStats.MasteryRating));
            retVal.Add("Mana Regen", String.Format("{0:F0}", ManaRegen * 5.0f));
            retVal.Add("Total Score", String.Format("{0:F2}", OverallPoints));
            retVal.Add("Selected Rotation", String.Format("*{0}", SelectedRotation.Name));
            retVal.Add("Selected DPS", String.Format("{0:F2}", SelectedRotation.SustainedDPS));
            retVal.Add("Selected Time To OOM", String.Format(SelectedRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", SelectedRotation.TimeToOOM.Minutes, SelectedRotation.TimeToOOM.Seconds));
            retVal.Add("Selected Cycle Length", String.Format("{0:F1} s", SelectedRotation.Duration));

            StringBuilder sb = new StringBuilder("*");
            float rotationDamage = SelectedRotation.SustainedDPS * SelectedRotation.Duration;
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount / rotationDamage,
                SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount,
                SelectedRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts / rotationDamage,
                (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts,
                SelectedRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * SelectedRotation.InsectSwarmAvgHit * SelectedRotation.InsectSwarmCasts / rotationDamage,
                SelectedRotation.InsectSwarmAvgHit * (SelectedRotation.InsectSwarmCasts),
                SelectedRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount / rotationDamage,
                SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount,
                SelectedRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount / rotationDamage,
                SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount,
                SelectedRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts / rotationDamage,
                SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts,
                SelectedRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts / rotationDamage,
                SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts,
                SelectedRotation.MushroomCasts));

            retVal.Add("Selected Spell Breakdown", sb.ToString());

            retVal.Add("Burst Rotation", String.Format("*{0}", BurstRotation.Name));
            retVal.Add("Burst DPS", String.Format("{0:F2}", BurstRotation.BurstDPS));
            retVal.Add("Burst Time To OOM", String.Format(BurstRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", BurstRotation.TimeToOOM.Minutes, BurstRotation.TimeToOOM.Seconds));
            retVal.Add("Burst Cycle Length", String.Format("{0:F1} s", BurstRotation.Duration));

            sb = new StringBuilder("*");
            rotationDamage = BurstRotation.BurstDPS * BurstRotation.Duration;
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount / rotationDamage,
                BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount,
                BurstRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts / rotationDamage,
                (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts,
                BurstRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * BurstRotation.InsectSwarmAvgHit * BurstRotation.InsectSwarmCasts / rotationDamage,
                BurstRotation.InsectSwarmAvgHit * (BurstRotation.InsectSwarmCasts),
                BurstRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * BurstRotation.WrathAvgHit * BurstRotation.WrathCount / rotationDamage,
                BurstRotation.WrathAvgHit * BurstRotation.WrathCount,
                BurstRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount / rotationDamage,
                BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount,
                BurstRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * BurstRotation.StarfallDamage * BurstRotation.StarfallCasts / rotationDamage,
                BurstRotation.StarfallDamage * BurstRotation.StarfallCasts,
                BurstRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * BurstRotation.MushroomDamage * BurstRotation.MushroomCasts / rotationDamage,
                BurstRotation.MushroomDamage * BurstRotation.MushroomCasts,
                BurstRotation.MushroomCasts));

            retVal.Add("Burst Spell Breakdown", sb.ToString());

            retVal.Add("Nature's Grace Uptime", String.Format("{0:F2}%", SelectedRotation.NaturesGraceUptime * 100));
            retVal.Add("Solar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.SolarUptime * 100));
            retVal.Add("Lunar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.LunarUptime * 100));

            retVal.Add("Starfire", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                SelectedRotation.StarfireAvgHit / (SelectedRotation.StarfireAvgCast > 0 ? SelectedRotation.StarfireAvgCast : 1f),
                SelectedRotation.StarfireAvgCast,
                SelectedRotation.StarfireAvgHit,
                SelectedRotation.StarfireAvgEnergy));
            retVal.Add("Wrath", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                SelectedRotation.WrathAvgHit / (SelectedRotation.WrathAvgCast > 0 ? SelectedRotation.WrathAvgCast : 1f),
                SelectedRotation.WrathAvgCast,
                SelectedRotation.WrathAvgHit,
                SelectedRotation.WrathAvgEnergy));
            retVal.Add("Starsurge", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                SelectedRotation.StarSurgeAvgHit / (SelectedRotation.StarSurgeAvgCast > 0 ? SelectedRotation.StarSurgeAvgCast : 1f),
                SelectedRotation.StarSurgeAvgCast,
                SelectedRotation.StarSurgeAvgHit,
                SelectedRotation.StarSurgeAvgEnergy));
            retVal.Add("Moonfire", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                SelectedRotation.MoonfireAvgHit / (SelectedRotation.MoonfireDuration > 0 ? SelectedRotation.MoonfireDuration : 1f),
                SelectedRotation.MoonfireAvgCast,
                SelectedRotation.MoonfireAvgHit));
            retVal.Add("Insect Swarm", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                SelectedRotation.InsectSwarmAvgHit / (SelectedRotation.InsectSwarmDuration > 0 ? SelectedRotation.InsectSwarmDuration : 1f),
                SelectedRotation.InsectSwarmAvgCast,
                SelectedRotation.InsectSwarmAvgHit));
            retVal.Add("Starfall", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per star",
                SelectedRotation.StarfallDamage / 10.0f,
                SelectedRotation.StarfallDamage,
                SelectedRotation.StarfallDamage / (SelectedRotation.StarfallStars > 0 ? SelectedRotation.StarfallStars : 1f)));
            retVal.Add("Treants", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per tree",
                SelectedRotation.TreantDamage / 30.0f, SelectedRotation.TreantDamage, SelectedRotation.TreantDamage / 3.0f));
            retVal.Add("Wild Mushroom", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per mushroom",
                SelectedRotation.MushroomDamage / 10.0f,
                SelectedRotation.MushroomDamage,
                SelectedRotation.MushroomDamage / 3f));

            return retVal;
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> retVal = new Dictionary <string, string>();

            //
            if (baseStats == null)
            {
                baseStats = new StatsMoonkin();
            }
            if (SelectedRotation == null)
            {
                SelectedRotation = new RotationData();
            }
            if (BurstRotation == null)
            {
                BurstRotation = new RotationData();
            }
            //
            retVal.Add("Health", baseStats.Health.ToString());
            retVal.Add("Mana", baseStats.Mana.ToString());
            retVal.Add("Armor", baseStats.Armor.ToString());
            retVal.Add("Agility", baseStats.Agility.ToString());
            retVal.Add("Stamina", baseStats.Stamina.ToString());
            retVal.Add("Intellect", baseStats.Intellect.ToString());
            retVal.Add("Spirit", baseStats.Spirit.ToString());
            retVal.Add("Spell Power", SpellPower.ToString());

            float totalHitDelta = SpellHitCap - SpellHit;

            retVal.Add("Spell Hit", String.Format("{0:F}%*{1} Hit Rating, {2:F}% Hit From Gear" + (totalHitDelta != 0 ? ", {3} Rating {4}" : ""),
                                                  100 * SpellHit,
                                                  baseStats.HitRating,
                                                  100 * StatConversion.GetSpellHitFromRating(baseStats.HitRating),
                                                  StatConversion.GetRatingFromHit(Math.Abs(totalHitDelta)),
                                                  totalHitDelta > 0 ? "To Cap" : "Over Cap"));
            retVal.Add("Spell Crit", String.Format("{0:F}%*{1} Crit Rating, {2:F}% Crit From Gear, {3:F}% Crit From Intellect",
                                                   100 * SpellCrit,
                                                   baseStats.CritRating,
                                                   100 * StatConversion.GetSpellCritFromRating(baseStats.CritRating),
                                                   100 * StatConversion.GetSpellCritFromIntellect(baseStats.Intellect)));
            retVal.Add("Spell Haste", String.Format("{0:F}%*{1} Haste Rating, {2:F}% Haste From Gear",
                                                    100 * SpellHaste,
                                                    baseStats.HasteRating,
                                                    100 * StatConversion.GetSpellHasteFromRating(baseStats.HasteRating)));
            retVal.Add("Mastery", String.Format("{0:F}*{1:F} Eclipse %, {2} Rating",
                                                Mastery,
                                                Mastery * 2.0f,
                                                baseStats.MasteryRating));
            retVal.Add("Mana Regen", String.Format("{0:F0}", ManaRegen * 5.0f));
            retVal.Add("Total Score", String.Format("{0:F2}", OverallPoints));
            retVal.Add("Selected Rotation", String.Format("*{0}", SelectedRotation.Name));
            retVal.Add("Selected DPS", String.Format("{0:F2}", SelectedRotation.SustainedDPS));
            retVal.Add("Selected Time To OOM", String.Format(SelectedRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", SelectedRotation.TimeToOOM.Minutes, SelectedRotation.TimeToOOM.Seconds));
            retVal.Add("Selected Cycle Length", String.Format("{0:F1} s", SelectedRotation.Duration));

            StringBuilder sb             = new StringBuilder("*");
            float         rotationDamage = SelectedRotation.SustainedDPS * SelectedRotation.Duration;

            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount / rotationDamage,
                                        SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount,
                                        SelectedRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts / rotationDamage,
                                        (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts,
                                        SelectedRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * SelectedRotation.InsectSwarmAvgHit * SelectedRotation.InsectSwarmCasts / rotationDamage,
                                        SelectedRotation.InsectSwarmAvgHit * (SelectedRotation.InsectSwarmCasts),
                                        SelectedRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount / rotationDamage,
                                        SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount,
                                        SelectedRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount / rotationDamage,
                                        SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount,
                                        SelectedRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts / rotationDamage,
                                        SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts,
                                        SelectedRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts / rotationDamage,
                                        SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts,
                                        SelectedRotation.MushroomCasts));

            retVal.Add("Selected Spell Breakdown", sb.ToString());

            retVal.Add("Burst Rotation", String.Format("*{0}", BurstRotation.Name));
            retVal.Add("Burst DPS", String.Format("{0:F2}", BurstRotation.BurstDPS));
            retVal.Add("Burst Time To OOM", String.Format(BurstRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", BurstRotation.TimeToOOM.Minutes, BurstRotation.TimeToOOM.Seconds));
            retVal.Add("Burst Cycle Length", String.Format("{0:F1} s", BurstRotation.Duration));

            sb             = new StringBuilder("*");
            rotationDamage = BurstRotation.BurstDPS * BurstRotation.Duration;
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount / rotationDamage,
                                        BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount,
                                        BurstRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts / rotationDamage,
                                        (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts,
                                        BurstRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * BurstRotation.InsectSwarmAvgHit * BurstRotation.InsectSwarmCasts / rotationDamage,
                                        BurstRotation.InsectSwarmAvgHit * (BurstRotation.InsectSwarmCasts),
                                        BurstRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * BurstRotation.WrathAvgHit * BurstRotation.WrathCount / rotationDamage,
                                        BurstRotation.WrathAvgHit * BurstRotation.WrathCount,
                                        BurstRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount / rotationDamage,
                                        BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount,
                                        BurstRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * BurstRotation.StarfallDamage * BurstRotation.StarfallCasts / rotationDamage,
                                        BurstRotation.StarfallDamage * BurstRotation.StarfallCasts,
                                        BurstRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * BurstRotation.MushroomDamage * BurstRotation.MushroomCasts / rotationDamage,
                                        BurstRotation.MushroomDamage * BurstRotation.MushroomCasts,
                                        BurstRotation.MushroomCasts));

            retVal.Add("Burst Spell Breakdown", sb.ToString());

            retVal.Add("Nature's Grace Uptime", String.Format("{0:F2}%", SelectedRotation.NaturesGraceUptime * 100));
            retVal.Add("Solar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.SolarUptime * 100));
            retVal.Add("Lunar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.LunarUptime * 100));

            retVal.Add("Starfire", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                                 SelectedRotation.StarfireAvgHit / (SelectedRotation.StarfireAvgCast > 0 ? SelectedRotation.StarfireAvgCast : 1f),
                                                 SelectedRotation.StarfireAvgCast,
                                                 SelectedRotation.StarfireAvgHit,
                                                 SelectedRotation.StarfireAvgEnergy));
            retVal.Add("Wrath", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                              SelectedRotation.WrathAvgHit / (SelectedRotation.WrathAvgCast > 0 ? SelectedRotation.WrathAvgCast : 1f),
                                              SelectedRotation.WrathAvgCast,
                                              SelectedRotation.WrathAvgHit,
                                              SelectedRotation.WrathAvgEnergy));
            retVal.Add("Starsurge", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                                  SelectedRotation.StarSurgeAvgHit / (SelectedRotation.StarSurgeAvgCast > 0 ? SelectedRotation.StarSurgeAvgCast : 1f),
                                                  SelectedRotation.StarSurgeAvgCast,
                                                  SelectedRotation.StarSurgeAvgHit,
                                                  SelectedRotation.StarSurgeAvgEnergy));
            retVal.Add("Moonfire", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                                                 SelectedRotation.MoonfireAvgHit / (SelectedRotation.MoonfireDuration > 0 ? SelectedRotation.MoonfireDuration : 1f),
                                                 SelectedRotation.MoonfireAvgCast,
                                                 SelectedRotation.MoonfireAvgHit));
            retVal.Add("Insect Swarm", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                                                     SelectedRotation.InsectSwarmAvgHit / (SelectedRotation.InsectSwarmDuration > 0 ? SelectedRotation.InsectSwarmDuration : 1f),
                                                     SelectedRotation.InsectSwarmAvgCast,
                                                     SelectedRotation.InsectSwarmAvgHit));
            retVal.Add("Starfall", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per star",
                                                 SelectedRotation.StarfallDamage / 10.0f,
                                                 SelectedRotation.StarfallDamage,
                                                 SelectedRotation.StarfallDamage / (SelectedRotation.StarfallStars > 0 ? SelectedRotation.StarfallStars : 1f)));
            retVal.Add("Treants", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per tree",
                                                SelectedRotation.TreantDamage / 30.0f, SelectedRotation.TreantDamage, SelectedRotation.TreantDamage / 3.0f));
            retVal.Add("Wild Mushroom", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per mushroom",
                                                      SelectedRotation.MushroomDamage / 10.0f,
                                                      SelectedRotation.MushroomDamage,
                                                      SelectedRotation.MushroomDamage / 3f));

            return(retVal);
        }