private void btnContainerGroup_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                DestructibleContainer[] containers = null;
                ContainerGroup group = null;

                #region test1

                // Set up 3 containers with different sizes
                containers = new[]
                {
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 100 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 50 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 70 },
                };

                group = new ContainerGroup() { Ownership = ContainerGroup.ContainerOwnershipType.GroupIsSoleOwner };

                foreach (var container in containers)
                    group.AddContainer(container);

                // Fill them all up
                group.AddQuantity(group.QuantityMax, false);

                // Add more
                group.AddQuantity(10, false);

                // Destroy one
                containers[1].IsDestroyed = true;

                // Add more
                group.AddQuantity(5, false);

                // Repair
                containers[1].IsDestroyed = false;

                // Add more
                group.AddQuantity(5, false);

                #endregion
                #region test 2

                // Set up 3 containers with different sizes
                containers = new[]
                {
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 100 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 50 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 70 },
                };

                group = new ContainerGroup() { Ownership = ContainerGroup.ContainerOwnershipType.GroupIsSoleOwner };

                foreach (var container in containers)
                    group.AddContainer(container);

                // Fill them all up
                group.AddQuantity(group.QuantityMax, false);

                // Remove some
                group.RemoveQuantity(5, false);

                // Destroy one
                containers[0].IsDestroyed = true;

                // Remove more
                group.RemoveQuantity(10, false);

                // Fix it
                containers[0].IsDestroyed = false;

                // Remove more
                group.RemoveQuantity(2, false);

                #endregion
                #region test 3

                // Set up 3 containers with different sizes
                containers = new[]
                {
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 100 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 50 },
                    new DestructibleContainer() { HitPoints_Max = 1, HitPoints_Current = 1, QuantityMax = 70 },
                };

                group = new ContainerGroup() { Ownership = ContainerGroup.ContainerOwnershipType.GroupIsSoleOwner };

                foreach (var container in containers)
                    group.AddContainer(container);

                // Fill them halfway
                group.AddQuantity(group.QuantityMax / 2, false);

                // Destroy one
                containers[2].IsDestroyed = true;

                // Repair it
                containers[2].IsDestroyed = false;

                // Destroy again
                containers[2].IsDestroyed = true;

                // Repair it
                containers[2].IsDestroyed = false;

                // Add some
                group.AddQuantity(15, false);

                // Remove some
                group.RemoveQuantity(5, false);

                #endregion
                #region test 4

                // Delete two containers from 2 different threads as close to simulataneous as possible
                //
                // The group will see the first destruction, try to rebalance.  It will only know about one destruction and will be off
                // Then the second destruction will be registered, and another rebalance will occur - but quantities will be off
                //
                // While it's possible this could happen, it's more likely that a dual destruction will happen in one thread.  The event listener
                // is called from that destroying thread, so everything will work out

                #endregion
                #region test 5

                // Set up threads that hammer it with rapid destoy/repair add/remove

                // Look for quantities trending to empty or full vs staying stable

                // If containers are getting destroyed and repaired that rapidly, I don't know if it matters if some quantity is lost.  Just make sure no exceptions occur

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void btnMultiEnergy_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                List<EnergyTank> tanks = new List<EnergyTank>();
                ContainerGroup group = new ContainerGroup();
                group.Ownership = ContainerGroup.ContainerOwnershipType.GroupIsSoleOwner;

                for (int cntr = 0; cntr < 3; cntr++)
                {
                    ShipPartDNA dna = GetDefaultDNA(EnergyTank.PARTTYPE);
                    double xy = _rand.NextDouble() * 3d;
                    double z = _rand.NextDouble() * 3d;
                    dna.Scale = new Vector3D(xy, xy, z);

                    EnergyTank energyTank = new EnergyTank(_editorOptions, _itemOptions, dna);

                    tanks.Add(energyTank);
                    group.AddContainer(energyTank);
                }

                #region Test1

                double max = group.QuantityMax;

                double remainder1 = group.AddQuantity(max * .5d, false);
                double remainder2 = group.RemoveQuantity(max * .25d, false);
                double remainder3 = group.RemoveQuantity(max * .33d, true);		// should fail
                double remainder4 = group.AddQuantity(max, false);		// partial add

                group.QuantityCurrent *= .5d;

                group.RemoveContainer(tanks[0], false);
                group.AddContainer(tanks[0]);

                group.RemoveContainer(tanks[0], true);
                group.AddContainer(tanks[0]);

                #endregion

                //TODO: Finish these
                //TODO: Test setting max (with just regular containers)

                #region Test2

                group.QuantityCurrent = 0d;

                group.Ownership = ContainerGroup.ContainerOwnershipType.GroupIsSoleOwner;
                //group.Ownership = ContainerGroup.ContainerOwnershipType.QuantitiesCanChange;

                tanks[0].QuantityCurrent *= .5d;		// this will make sole owner fail, but the second enum will handle it

                group.QuantityCurrent = max * .75d;

                group.RemoveQuantity(max * .33d, false);
                group.AddQuantity(max * .5d, false);

                group.RemoveContainer(tanks[0], true);
                group.AddContainer(tanks[0]);

                #endregion

                #region Test3

                group.OnlyRemoveMultiples = true;
                group.RemovalMultiple = max * .25d;

                group.QuantityCurrent = group.QuantityMax;

                double rem1 = group.RemoveQuantity(max * .1d, false);
                double rem2 = group.RemoveQuantity(max * .1d, true);

                group.QuantityCurrent = group.QuantityMax;

                double rem3 = group.RemoveQuantity(max * .3d, false);
                double rem4 = group.RemoveQuantity(max * .3d, true);

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }