Inheritance: IContext
        public void TestShieldBoosterStats()
        {
            var ship = _service.CreateShip("Enyo");
            var items = _service.CreateItems(
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Medium Ancillary Shield Booster",
                                             "Small Shield Booster II",
                                             "Small Ancillary Armor Repairer",
                                             "Coreli A-Type Explosive Plating",
                                             "Small Armor Repairer II",
                                             "Internal Force Field Array I",
                                             "Small Hybrid Burst Aerator I",
                                             "Small Hybrid Collision Accelerator I");

            var context = new Context
                          {
                              Ship = ship,
                              Target = _service.CreateItem("Rifter"),
                              Char = _service.GetAllVCharacter(),
                              Area = new Item()
                          };
            context.Char.InstalledItems.Add(ship);
            ship.InstalledItems.AddRange(items);

            context.Char.Activate(context);

        Assert.AreEqual(145.88, ship.Tank.GetActiveShieldTankPerSecond(), 0.005);
            
        }
        public void EnyoTest()
        {
            var ship = _service.CreateItem("Enyo");
            var items = _service.CreateItems("Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "1MN Afterburner II",
                                             "X5 Prototype Engine Enervator",
                                             "Initiated Harmonic Warp Scrambler I",
                                             "Magnetic Field Stabilizer II",
                                             "Coreli A-Type Explosive Plating",
                                             "Magnetic Field Stabilizer II",
                                             "Internal Force Field Array I",
                                             "Small Hybrid Burst Aerator I",
                                             "Small Hybrid Collision Accelerator I");

            var blaster = items.Where(x => x.TypeName == "Light Neutron Blaster II")
                               .ToArray();

            foreach (var curBlaster in blaster)
            {
                var ammo = _service.CreateItem("Federation Navy Antimatter Charge S");
                curBlaster.InstalledItems.Add(ammo);
            }

            var context = new Context()
                              {
                                  Ship = ship,
                                  Target = _service.CreateItem("Rifter"),
                                  Char = new Item()
                              };

            ship.InstalledItems.AddRange(items);
            ship.Activate(context);
            //TODO enums
            var damageAttributIds = new[] {114, 116, 117, 118};
            foreach (var item in blaster)
            {
                var multiplier = item.Attributes.First(x => x.AttributeName == "damageMultiplier").Value;
                var damageByTypes = item.InstalledItems.First()
                                        .Attributes.Where(x => damageAttributIds.Contains(x.AttributeID))
                                        .ToDictionary(x => x.AttributeID, x => x.Value);
                var cycleTime = item.Attributes.First(x => x.AttributeName == "speed");
                var damage = new Damage()
                                 {
                                     EM = damageByTypes[114] * multiplier,
                                     Explosive = damageByTypes[116] * multiplier,
                                     Kinetic = damageByTypes[117] * multiplier,
                                     Thermal = damageByTypes[118] * multiplier,
                                     CycleTime = new TimeSpan(0, 0, 0, 0, (int) cycleTime.Value)
                                 };

                Assert.AreEqual(31.522, damage.DamagePerSecond, 0.001);
            }
        }
        public FittingAnalysisViewModel(Context context)
        {
            var ship = (Ship) context.Ship;
            DamageAnalysis.AddDrones(ship);

            context.Char.Online(context);
            BaseVelocity = ship.MaxVelocityInMetersPerSecond;

            context.Char.Activate(context);
            PropulsionModVelocity = ship.MaxVelocityInMetersPerSecond;

            context.Char.Overload(context);
            HeatedPropulsionModVelocity = ship.MaxVelocityInMetersPerSecond;

            InitDamage(context);
            InitTank(ship);
        }
 public void Init()
 {
     _stack = new Stack<object>();
     _ship = new FittingService().CreateTestShip("Rifter");
     _area = new Item();
     _char = new Item();
     _target = new Item();
     _self = new Item();
     _other = new Item();
     _context = new Context {
                                Ship = _ship,
                                Area = _area,
                                Char = _char,
                                Target = _target,
                                Other = _other,
                                Self = _self
                            };
 }
        public static DamageOutput GetDamageOutput(Context context)
        {
            var ship = (Ship)context.Ship;

            WeaponSystem weaponSystem;
           
            var entries = ship.InstalledItems.Where(x => TryGetWeaponSystem(x, out weaponSystem))
                .GroupBy(x => x.TypeId)
                .Select(
                        x =>
                        {
                            var entry = GetDamageEntry(context, x.First());
                            entry.WeaponCount = x.Count();
                            return entry;
                        })
                .ToList();

            return new DamageOutput
                   {
                       Entries = entries
                   };
        }
        public void TestTurretStats()
        {
            var ship = _service.CreateShip("Republic Fleet Firetail");
            var items = _service.CreateItems(

                                             "150mm Light AutoCannon II", "Gyrostabilizer II"
                                            );

            var context = new Context
            {
                Ship = ship,
                Target = _service.CreateItem("Rifter"),
                Char = _service.GetAllVCharacter(),
                Area = new Item()
            };
            context.Char.InstalledItems.Add(ship);
            ship.InstalledItems.AddRange(items);
            context.Char.Activate(context);
            var damageOutput = context.GetDamageOutput();
            Assert.AreEqual(73.753, damageOutput.Entries.Sum(x => x.AmmoEntries.First().Damage.DamagePerSecond), 0.001);

            
        }
        private static DamageOutput.WeaponEntry.AmmoEntry GetAmmoEntry(Context parentContext, Item weapon, Item ammoItem)
        {
            //TODO evtl. ship copy um damage fuer modul etc. richtig zu haben :(
            var context = new Context
                          {
                              Other = weapon
                          };
            weapon.UninstallItems(context);
            weapon.InstalledItems.Add(ammoItem);

            parentContext.Char.Online(parentContext);
            parentContext.Char.Activate(parentContext);


            const double MILLISECONDS_PER_SECOND = 1000.0;
            const double METERS_PER_KM = 1000.0;

            var flightTimeInMilliseconds = (ammoItem.GetAttributeByIdOrNull(FLIGHT_TIME_ID)
                ?.Value).GetValueOrDefault();
            var velocityInMeterPerSecond = (ammoItem.GetAttributeByIdOrNull(VELOCITY_ID)
                ?.Value).GetValueOrDefault();

            return new DamageOutput.WeaponEntry.AmmoEntry
                   {
                       AmmoType = AmmoType.Faction,
                       Ammunition = ammoItem.TypeName,
                       Damage = GetDamage(weapon, ammoItem),
                       OptimalInKm = (weapon.GetAttributeByIdOrNull(OPTIMAL_ID)
                                         ?.Value ?? (flightTimeInMilliseconds * velocityInMeterPerSecond / METERS_PER_KM)) / MILLISECONDS_PER_SECOND,
                       FalloffInKm = (weapon.GetAttributeByIdOrNull(FALLOFF_ID)
                                         ?.Value).GetValueOrDefault() / MILLISECONDS_PER_SECOND,
                       TrackingInRadPerSecond = (weapon.GetAttributeByIdOrNull(TRACKING_ID)
                           ?.Value).GetValueOrDefault(),
                       ExplosionVelocity = (ammoItem.GetAttributeByIdOrNull(EXPLOSION_VELOCITY_ID)
                           ?.Value).GetValueOrDefault(),
                       VelocityInMeterPerSecond = velocityInMeterPerSecond,
                       FlightTimeInMilliseconds = flightTimeInMilliseconds,
                   };
        }
        public static DamageOutput.WeaponEntry GetDamageEntry(Context context, Item item)
        {
            WeaponSystem weaponSystem;
            if (!TryGetWeaponSystem(item, out weaponSystem))
            {
                throw new ArgumentException("invalid item group for weapon analysis: " + item.GroupId);
            }

            List<DamageOutput.WeaponEntry.AmmoEntry> ammoEntries = new List<DamageOutput.WeaponEntry.AmmoEntry>();

            if (!IsNeedingAmmo(weaponSystem))
            {
                ammoEntries.Add(
                                new DamageOutput.WeaponEntry.AmmoEntry
                                {
                                    Ammunition = "(none)",
                                    Damage = GetDamage(item, item),
                                    OptimalInKm = item.GetAttributeById(OPTIMAL_ID)
                                                      .Value / 1000.0,
                                    FalloffInKm = item.GetAttributeById(FALLOFF_ID)
                                                      .Value / 1000.0,
                                    TrackingInRadPerSecond = item.GetAttributeById(TRACKING_ID)
                                        .Value
                                });
            }
            else
            {
                //TODO create service/DI
                using (var service = new FittingService())
                {
                    var ammo = new Ammo(service);

                    var factionAmmo = ammo.GetFactionAmmoForWeapon(item);
                    if (factionAmmo != null)
                    {
                        var factionEntry = GetAmmoEntry(context, item, factionAmmo);
                        ammoEntries.Add(factionEntry);
                    }

                    var t2Range = ammo.GetLongRangeT2AmmoForWeapon(item);
                    if (t2Range != null)
                    {
                        var t2RangeEntry = GetAmmoEntry(context, item, t2Range);
                        ammoEntries.Add(t2RangeEntry);
                    }

                    var t2Dps = ammo.GetHighDamageT2AmmoForWeapon(item);
                    if (t2Dps != null)
                    {
                        var t2DpsEntry = GetAmmoEntry(context, item, t2Dps);
                        ammoEntries.Add(t2DpsEntry);
                    }
                }
            }

            return new DamageOutput.WeaponEntry
                   {
                       AmmoEntries = ammoEntries.ToArray(),
                       WeaponSystem = weaponSystem,
                       WeaponType = item.TypeName
                   };
        }
        public void ShowShip(Context context)
        {
            Task.Factory.StartNew(
                                  () =>
                                  {
                                      FittingAnalysisViewModel viewModel = null;
                                      try
                                      {
                                          viewModel = new FittingAnalysisViewModel(context);
                                      }
                                      catch (Exception e)
                                      {
                                          Log.Logger.Warning(e, "Error in accessing fitting stats");
                                          //TODO messagebox? / visibility??
                                      }

                                      Application.Current.Dispatcher.Invoke(() => { DataContext = viewModel; });
                                  },
                                  TaskCreationOptions.LongRunning);
        }
 private void InitDamage(Context context)
 {
     var damageOutput = context.GetDamageOutput();
     MaxAlpha = damageOutput.Entries.Sum(entry => entry.WeaponCount * entry.AmmoEntries.Max(x => x.Damage.AlphaDamage));
     MaxDps = damageOutput.Entries.Sum(entry => entry.WeaponCount * entry.AmmoEntries.Max(x => x.Damage.DamagePerSecond));
     AmmoAnalysis = damageOutput.Entries.SelectMany(x => x.AmmoEntries.Select(a => CreateAmmoAnalysisViewModel(x, a)))
         .ToArray();
 }
        public void TestDamageOutput()
        {

            var start = DateTime.UtcNow;
        //    CrestSharp.Crest.Settings.Cache = new CrestCacheWithSessionCache(new CrestSqliteCache());
        CrestSharp.Crest.Settings.Cache = new CrestSqliteCache();
            var allVCharacter = _service.GetAllVCharacter();
            var copy = allVCharacter.Copy();


            var ship = _service.CreateShip("Ishtar");
            //TODO distinct und bei mehreren dann copy verwenden
            var items = _service.CreateItems("Drone Damage Amplifier II", "Drone Damage Amplifier II", "Dual 180mm AutoCannon II", "Dual 180mm AutoCannon II", "Dual 180mm AutoCannon II");
            var gun = _service.CreateItem("Dual 180mm AutoCannon II");
            ship.InstalledItems.AddRange(items);

            //TODO new DamageAnalysis(_service);
            DamageAnalysis.AddDrones(ship);

            Assert.AreEqual(5, ship.InstalledItems.Count(x => x.TypeName == "Ogre II"));

            var ammo = new Ammo(_service).GetFactionAmmoForWeapon(gun);
            foreach (var curItem in items.Where(x => x.TypeName == gun.TypeName))
            {
                curItem.InstalledItems.Add(ammo);
            }

            var context = new Context
            {
                Ship = ship,
                Target = _service.CreateItem("Rifter"),
                Char = allVCharacter,
                Area = new Item()
            };
            context.Char.InstalledItems.Add(ship);
            context.Char.Activate(context);
            Console.WriteLine($"time: {(DateTime.UtcNow - start).TotalSeconds}s");
            var damage = DamageAnalysis.GetDamageOutput(context);
            Assert.AreEqual(2, damage.Entries.Count());


        }
        public void TestStats()
        {
            var ship = _service.CreateItem("Enyo");
            var items = _service.CreateItems(
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "1MN Afterburner II",
                                             "X5 Prototype Engine Enervator",
                                             "Initiated Harmonic Warp Scrambler I",
                                             "Magnetic Field Stabilizer II",
                                             "Coreli A-Type Explosive Plating",
                                             "Magnetic Field Stabilizer II",
                                             "Internal Force Field Array I",
                                             "Small Hybrid Burst Aerator I",
                                             "Small Hybrid Collision Accelerator I");

            var context = new Context
                          {
                              Ship = ship,
                              Target = _service.CreateItem("Rifter"),
                              Char = _service.GetAllVCharacter(),
                              Area = new Item()
                          };
            context.Char.InstalledItems.Add(ship);
            ship.InstalledItems.AddRange(items);

            context.Char.Activate(context);

            var hullResistance = new ResistanceProfile
                                 {
                                     EmResistance = 1.0 - ship.GetAttributeById((int) HullDamageResonanceAttribute.EmDamage)
                                                              .Value,
                                     KineticResistance = 1.0 - ship.GetAttributeById((int) HullDamageResonanceAttribute.KineticDamage)
                                                                   .Value,
                                     ThermalResistance = 1.0 - ship.GetAttributeById((int) HullDamageResonanceAttribute.ThermalDamage)
                                                                   .Value,
                                     ExplosiveResistance = 1.0 - ship.GetAttributeById((int) HullDamageResonanceAttribute.ExplosiveDamage)
                                                                     .Value
                                 };

            Assert.AreEqual(0.58, hullResistance.EmResistance, 0.0001);
            Assert.AreEqual(0.58, hullResistance.KineticResistance, 0.0001);
            Assert.AreEqual(0.58, hullResistance.ThermalResistance, 0.0001);
            Assert.AreEqual(0.58, hullResistance.ExplosiveResistance, 0.0001);

            var shieldResistance = new ResistanceProfile
                                   {
                                       EmResistance = 1.0 - ship.GetAttributeById((int) ShieldDamageResonanceAttribute.EmDamage)
                                                                .Value,
                                       KineticResistance = 1.0 - ship.GetAttributeById((int) ShieldDamageResonanceAttribute.KineticDamage)
                                                                     .Value,
                                       ThermalResistance = 1.0 - ship.GetAttributeById((int) ShieldDamageResonanceAttribute.ThermalDamage)
                                                                     .Value,
                                       ExplosiveResistance =
                                           1.0 - ship.GetAttributeById((int) ShieldDamageResonanceAttribute.ExplosiveDamage)
                                                     .Value
                                   };

            Assert.AreEqual(0.115, shieldResistance.EmResistance, 0.0001);
            Assert.AreEqual(0.8673, shieldResistance.KineticResistance, 0.0001);
            Assert.AreEqual(0.646, shieldResistance.ThermalResistance, 0.0001);
            Assert.AreEqual(0.5575, shieldResistance.ExplosiveResistance, 0.0001);

            var armorResistance = new ResistanceProfile
                                  {
                                      EmResistance = 1.0 - ship.GetAttributeById((int) ArmorDamageResonanceAttribute.EmDamage)
                                                               .Value,
                                      KineticResistance = 1.0 - ship.GetAttributeById((int) ArmorDamageResonanceAttribute.KineticDamage)
                                                                    .Value,
                                      ThermalResistance = 1.0 - ship.GetAttributeById((int) ArmorDamageResonanceAttribute.ThermalDamage)
                                                                    .Value,
                                      ExplosiveResistance = 1.0 - ship.GetAttributeById((int) ArmorDamageResonanceAttribute.ExplosiveDamage)
                                                                      .Value
                                  };

            Assert.AreEqual(0.57, armorResistance.EmResistance, 0.0001);
            Assert.AreEqual(0.8603, armorResistance.KineticResistance, 0.0001);
            Assert.AreEqual(0.7205, armorResistance.ThermalResistance, 0.0001);
            Assert.AreEqual(0.567, armorResistance.ExplosiveResistance, 0.0001);

            const int SHIELD_RECHARGE_RATE_ATTRIBUTE_ID = 479;

            var shieldRechargeRate = ship.GetAttributeById(SHIELD_RECHARGE_RATE_ATTRIBUTE_ID)
                .Value;

            const int SHIELD_CAPACITY_ATTRIBUTE_ID = 263;
            var shieldCapacity = ship.GetAttributeById(SHIELD_CAPACITY_ATTRIBUTE_ID)
                .Value;

            var shieldRecharge = new ShieldRecharge(shieldCapacity, shieldRechargeRate);
            
            Assert.AreEqual(
                            5.47,
                            Tank.CalculateTankInDps(shieldRecharge.PeakRecharge, shieldResistance, DamageProfile.OMNI_DAMAGE_PROFILE),
                            0.005);
        }
        public void TestArmorRepairerStats()
        {
            var ship = _service.CreateShip("Enyo");
            var items = _service.CreateItems(
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Light Neutron Blaster II",
                                             "Medium Ancillary Shield Booster",
                                             "Small Shield Booster II",
                                             "Small Ancillary Armor Repairer",
                                             "Coreli A-Type Explosive Plating",
                                             "Small Armor Repairer II",
                                             "Internal Force Field Array I",
                                             "Small Nanobot Accelerator I",
                                             "Small Hybrid Collision Accelerator I");

            var context = new Context
                          {
                              Ship = ship,
                              Target = _service.CreateItem("Rifter"),
                              Char = _service.GetAllVCharacter(),
                              Area = new Item()
                          };
            context.Char.InstalledItems.Add(ship);
            ship.InstalledItems.AddRange(items);

            context.Char.Activate(context);

            var resistanceProfile = ship.Tank.ArmorResitanceProfile;

            double armorRepPerSecond = 0;
            foreach (var curItem in ship.InstalledItems)
            {
                const int ARMOR_REPAIR_AMOUNT_ATTRIBUTE_ID = 84;
                const int CHARGED_ARMOR_DAMAGE_MULTIPLIER_ATTRIUBTE_ID = 1886;
                IAttribute armorRepairAmountAttribute;
                if (curItem.TryGetAttributeById(ARMOR_REPAIR_AMOUNT_ATTRIBUTE_ID, out armorRepairAmountAttribute))
                {
                    const int DURATION_ATTRIBUTE_ID = 73;
                    var durationInMs = curItem.GetAttributeById(DURATION_ATTRIBUTE_ID)
                        .Value;

                    IAttribute chargedDamageMultiplier;
                    double multiplier = curItem.TryGetAttributeById(
                                                                    CHARGED_ARMOR_DAMAGE_MULTIPLIER_ATTRIUBTE_ID,
                                                                    out chargedDamageMultiplier)
                                            ? chargedDamageMultiplier.Value
                                            : 1.0;

                    armorRepPerSecond += armorRepairAmountAttribute.Value * multiplier * 1000.0 / durationInMs;
                }
            }
            
            Assert.AreEqual(202.27, Tank.CalculateTankInDps(armorRepPerSecond, resistanceProfile), 0.005);
        }
        public void TestLoadDamageInvulnControl()
        {
            var ship = _service.CreateItem("Rifter");
            //   var damageControl = _service.CreateItem("Damage Control II");
            var item = _service.CreateItem("Adaptive Invulnerability Field II");
            var item2 = _service.CreateItem("Adaptive Invulnerability Field II");
            var item3 = _service.CreateItem("Adaptive Invulnerability Field II");
            var context = new Context()
                              {
                                  Ship = ship
                              };
            //      ship.InstalledItems.Add(damageControl);
            ship.InstalledItems.Add(item);
            ship.InstalledItems.Add(item2);
            ship.InstalledItems.Add(item3);
            ship.Activate(context);

            Assert.AreEqual(0.4289,
                            ship.Attributes.First(x => x.AttributeName == "shieldEmDamageResonance")
                                .Value,
                            0.0001);
        }
        public void TestLoadDamageControl()
        {
            var ship = _service.CreateItem("Rifter");
            var damageControl = _service.CreateItem("Damage Control II");

            var context = new Context()
                              {
                                  Ship = ship
                              };

            ship.InstalledItems.Add(damageControl);
            ship.Activate(context);

            Assert.AreEqual(0.4,
                            ship.Attributes.First(x => x.AttributeName == "emDamageResonance")
                                .Value);
            Assert.AreEqual(0.34,
                            ship.Attributes.First(x => x.AttributeName == "armorEmDamageResonance")
                                .Value);
            Assert.AreEqual(0.875,
                            ship.Attributes.First(x => x.AttributeName == "shieldEmDamageResonance")
                                .Value);
        }