public ITextureAtlas <TEnumKey> Build()
        {
            EnumDictionary.ThrowIfMissingEnumKey(this.swatches);

            var swatches = EnumDictionary.Create <TEnumKey, ITextureSwatch>();

            foreach (var pair in this.swatches)
            {
                swatches[pair.Key] = pair.Value;
            }

            return(new TextureAtlas <TEnumKey>(swatches));
        }
        public void EnumDictionary_ManOrBoy()
        {
            IDictionary <ExpressionType, bool> dictionary;

            var values = Enum.GetValues(typeof(ExpressionType)).Cast <ExpressionType>().ToArray();

            foreach (var setValue in values)
            {
                dictionary           = EnumDictionary.Create <ExpressionType, bool>();
                dictionary[setValue] = true;

                foreach (var testValue in values)
                {
                    Assert.AreEqual(testValue == setValue, dictionary.TryGetValue(testValue, out _));
                }
            }
        }
        public void EnumDictionary_Values()
        {
            var enumDictionary = EnumDictionary.Create <ExpressionType, int>();
            var values         = Enum.GetValues(typeof(ExpressionType)).Cast <ExpressionType>().ToArray();

            foreach (var val in values.Where(e => ((int)e) % 2 == 0))
            {
                enumDictionary.Add(val, (int)val);
            }

            var dictValues = enumDictionary.Values.ToArray();

            foreach (var value in values.Cast <int>())
            {
                Assert.AreEqual(value % 2 == 0, dictValues.Contains(value));
            }
        }
            // PERF: Expose the metrics as a struct that contains a reference to the long[] and provides
            //       dictionary-like APIs to reduce allocations.

            public IReadOnlyDictionary <EntityMetric, TimeSpan> GetMetrics(IReactiveResource entity)
            {
                var entityMetrics = GetEntityMetrics(entity);
                var results       = EnumDictionary.Create <EntityMetric, TimeSpan>();

                for (var i = 0; i < s_metricCount; ++i)
                {
                    var metric = entityMetrics[i];
                    if (metric >= 0)
                    {
                        results[(EntityMetric)i] = new TimeSpan(metric);
                    }
                }

                // CONSIDER: Consider whether we need to create a wrapper.

                return(new ReadOnlyDictionary <EntityMetric, TimeSpan>(results));
            }
        public void EnumDictionaryFactory_Parameter_Validation()
        {
            try
            {
                EnumDictionary.Create <int, bool>();
                Assert.Fail();
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(e.ParamName, "TKey");
            }

            try
            {
                EnumDictionary.Create <Foo, bool>();
                Assert.Fail();
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(e.ParamName, "TKey");
            }

            try
            {
                EnumDictionary.Create <Bar, bool>();
                Assert.Fail();
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(e.ParamName, "TKey");
            }

            try
            {
                EnumDictionary.Create <Baz, bool>();
                Assert.Fail();
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(e.ParamName, "TKey");
            }
        }
        public void EnumDictionary_Bounds_Checks()
        {
            var enumDictionary = EnumDictionary.Create <ExpressionType, bool>();
            var values         = Enum.GetValues(typeof(ExpressionType)).Cast <ExpressionType>().ToArray();

            try
            {
                enumDictionary.Add((ExpressionType)(-1), true);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.Add((ExpressionType)(values.Length), true);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary[(ExpressionType)(-1)] = true;
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary[(ExpressionType)(values.Length)] = true;
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                var dummy = enumDictionary[(ExpressionType)(-1)];
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                var dummy = enumDictionary[(ExpressionType)(values.Length)];
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.ContainsKey((ExpressionType)(-1));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.ContainsKey((ExpressionType)(values.Length));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.Contains(new KeyValuePair <ExpressionType, bool>((ExpressionType)(-1), true));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("item", e.ParamName);
            }

            try
            {
                enumDictionary.Contains(new KeyValuePair <ExpressionType, bool>((ExpressionType)(values.Length), true));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("item", e.ParamName);
            }

            try
            {
                enumDictionary.Remove((ExpressionType)(-1));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.Remove((ExpressionType)(values.Length));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("key", e.ParamName);
            }

            try
            {
                enumDictionary.Remove(new KeyValuePair <ExpressionType, bool>((ExpressionType)(-1), true));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("item", e.ParamName);
            }

            try
            {
                enumDictionary.Remove(new KeyValuePair <ExpressionType, bool>((ExpressionType)(values.Length), true));
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("item", e.ParamName);
            }

            try
            {
                enumDictionary.CopyTo(array: null, -1);
                Assert.Fail();
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual("array", e.ParamName);
            }

            try
            {
                enumDictionary.CopyTo(new KeyValuePair <ExpressionType, bool> [1], -1);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("index", e.ParamName);
            }

            enumDictionary = EnumDictionary.Create <ExpressionType, bool>();

            // This is valid because although the index is past the last array slot,
            // there are zero elements. This is the same behavior as the CopyTo in
            // System.Collections.Generic.Dictionary<TKey, TValue>
            enumDictionary.CopyTo(new KeyValuePair <ExpressionType, bool> [1], 1);

            try
            {
                enumDictionary.CopyTo(new KeyValuePair <ExpressionType, bool> [1], 3);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException e)
            {
                Assert.AreEqual("index", e.ParamName);
            }

            ExpressionType val0 = 0;
            ExpressionType val1 = (ExpressionType)1;

            enumDictionary.Add(val0, true);
            enumDictionary.Add(val1, true);
            try
            {
                enumDictionary.CopyTo(new KeyValuePair <ExpressionType, bool> [1], 0);
                Assert.Fail();
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(typeof(ArgumentException), e.GetType());
            }
        }
        CreateMaterialPropertiesTable(IFactory <int, INoise3D> noiseFactory)
        {
            Contracts.Requires.That(noiseFactory != null);

            var textureAtlasBuilder = new EnumKeyTextureAtlasBuilder <TerrainTexture>(
                atlasPixelDimensions: new Index2D(128, 128),
                swatchPixelDimensions: new Index2D(16, 16),
                invertXAxis: true,
                invertYAxis: false);

            textureAtlasBuilder.AddSwatch(TerrainTexture.None, new Index2D(0, 0));
            textureAtlasBuilder.AddSwatch(TerrainTexture.GrassFull, new Index2D(0, 1));
            textureAtlasBuilder.AddSwatch(TerrainTexture.GrassTop, new Index2D(1, 1));
            textureAtlasBuilder.AddSwatch(TerrainTexture.GrassBottom, new Index2D(2, 1));
            textureAtlasBuilder.AddSwatch(TerrainTexture.Dirt, new Index2D(0, 2));
            textureAtlasBuilder.AddSwatch(TerrainTexture.Stone, new Index2D(0, 3));

            var textureAtlas            = textureAtlasBuilder.Build();
            var materialPropertiesTable =
                EnumDictionary.Create <TerrainMaterial, ITerrainMaterialProperties <TSurfaceData> >();

            float areaThreshold  = .8f;
            var   noiseDistorter = NoiseDistorter.New().Frequency(100, 100, 100);
            var   noTexture      = new TextureSwatchSurfaceGenerator <TerrainVoxel, TSurfaceData>(
                textureAtlas[TerrainTexture.None]);

            materialPropertiesTable[TerrainMaterial.Air] = new TerrainMaterialProperties <TSurfaceData>(
                false,
                new ConstantSurfaceGenerator <TerrainVoxel, TSurfaceData, Color>(Color.Pink),
                noTexture);

            materialPropertiesTable[TerrainMaterial.Dirt] = new TerrainMaterialProperties <TSurfaceData>(
                true,
                new ConstantSurfaceGenerator <TerrainVoxel, TSurfaceData, Color>(new Color(120, 96, 56)),
                new AreaThresholdSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                    new NoiseSeedSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                        new SeedSwitchSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                            noTexture,
                            new SeedRangeSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                                .85f, 1f, new TextureSwatchSurfaceGenerator <TerrainVoxel, TSurfaceData>(
                                    textureAtlas[TerrainTexture.Dirt]))),
                        noiseFactory,
                        noiseDistorter),
                    noTexture,
                    areaThreshold));

            materialPropertiesTable[TerrainMaterial.Grass] = new TerrainMaterialProperties <TSurfaceData>(
                true,
                new ConstantSurfaceGenerator <TerrainVoxel, TSurfaceData, Color>(new Color(72, 160, 72)),
                new AreaThresholdSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                    new NoiseSeedSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                        new SeedSwitchSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                            noTexture,
                            new SeedRangeSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                                .85f, 1f, new TextureSwatchSurfaceGenerator <TerrainVoxel, TSurfaceData>(
                                    textureAtlas[TerrainTexture.GrassFull]))),
                        noiseFactory,
                        noiseDistorter),
                    noTexture,
                    areaThreshold));

            materialPropertiesTable[TerrainMaterial.Stone] = new TerrainMaterialProperties <TSurfaceData>(
                true,
                new ConstantSurfaceGenerator <TerrainVoxel, TSurfaceData, Color>(Color.Gray),
                new AreaThresholdSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                    new NoiseSeedSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                        new SeedSwitchSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                            noTexture,
                            new SeedRangeSurfaceGenerator <TerrainVoxel, TSurfaceData, Vector2>(
                                .85f, 1f, new TextureSwatchSurfaceGenerator <TerrainVoxel, TSurfaceData>(
                                    textureAtlas[TerrainTexture.Stone]))),
                        noiseFactory,
                        noiseDistorter),
                    noTexture,
                    areaThreshold));

            ////materialPropertiesTable[TerrainMaterial.Coal] = new TerrainMaterialProperties<TSurfaceData>(
            ////	true,
            ////	new ConstantSurfaceGenerator<TerrainVoxel, TSurfaceData, Color>(Color.Black),
            ////	noTexture);

            ////materialPropertiesTable[TerrainMaterial.Iron] = new TerrainMaterialProperties<TSurfaceData>(
            ////	true,
            ////	new ConstantSurfaceGenerator<TerrainVoxel, TSurfaceData, Color>(Color.DarkGray),
            ////	noTexture);

            ////materialPropertiesTable[TerrainMaterial.Gold] = new TerrainMaterialProperties<TSurfaceData>(
            ////	true,
            ////	new ConstantSurfaceGenerator<TerrainVoxel, TSurfaceData, Color>(Color.Gold),
            ////	noTexture);

            ////materialPropertiesTable[TerrainMaterial.Diamond] = new TerrainMaterialProperties<TSurfaceData>(
            ////	true,
            ////	new ConstantSurfaceGenerator<TerrainVoxel, TSurfaceData, Color>(Color.BlueViolet),
            ////	noTexture);

            EnumDictionary.ThrowIfMissingEnumKey(materialPropertiesTable);
            return(materialPropertiesTable);
        }