示例#1
0
 public SubstanceEntry(Substance substance, float moles)
 {
     Substance = substance;
     Moles     = moles;
 }
示例#2
0
        /// <summary>
        /// Processes substances in a container
        /// </summary>
        public void ProcessContainer(SubstanceContainer container)
        {
            float temperature = container.Temperature;

            // Process recipes
            foreach (Recipe recipe in recipes)
            {
                // Check temperature limits
                if (temperature < recipe.MinimalTemperature || temperature > recipe.MaximalTemperature)
                {
                    continue;
                }

                // Gather the mole amount of every substance
                float[] moles = new float[recipe.Ingredients.Length];
                bool    ingredientsPresent = true;
                for (var i = 0; i < recipe.Ingredients.Length; i++)
                {
                    ingredientsPresent = false;
                    foreach (var entry in container.Substances)
                    {
                        if (entry.Substance.Id == recipe.Ingredients[i].Id)
                        {
                            moles[i]           = entry.Moles;
                            ingredientsPresent = true;
                            break;
                        }
                    }

                    if (!ingredientsPresent)
                    {
                        break;
                    }
                }

                // Substance missing
                if (!ingredientsPresent)
                {
                    continue;
                }

                // Calculate the maximum amount of ingredients
                float totalIngredients = recipe.Ingredients.Sum(x => x.RelativeAmount);
                float maxConversion    = float.MaxValue;
                for (var i = 0; i < moles.Length; i++)
                {
                    float relativeAmount = recipe.Ingredients[i].RelativeAmount;
                    float part           = relativeAmount / totalIngredients;
                    float maxProduced    = moles[i] / part;
                    if (maxProduced < maxConversion)
                    {
                        maxConversion = maxProduced;
                    }
                }

                // Calculate relative volume of ingredients
                Substance[] ingredientSubstances = new Substance[moles.Length];
                float       ingredientsToVolume  = 0;
                for (var i = 0; i < moles.Length; i++)
                {
                    var component = recipe.Ingredients[i];
                    var substance = ingredientSubstances[i] = FromId(component.Id);
                    ingredientsToVolume += substance.MillilitersPerMole * component.RelativeAmount;
                }
                ingredientsToVolume /= totalIngredients;

                // Calculate relative volume of results
                float       totalResults     = recipe.Results.Sum(x => x.RelativeAmount);
                Substance[] resultSubstances = new Substance[recipe.Results.Length];
                float       resultsToVolume  = 0;
                for (var i = 0; i < recipe.Results.Length; i++)
                {
                    var component = recipe.Results[i];
                    var substance = resultSubstances[i] = FromId(component.Id);
                    resultsToVolume += substance.MillilitersPerMole * component.RelativeAmount;
                }
                resultsToVolume /= totalResults;

                // Limit the reaction to prevent spill
                // TODO: Spill container into surroundings
                float remainingVolume = container.RemainingVolume;
                if (maxConversion * totalResults * resultsToVolume - maxConversion * ingredientsToVolume > remainingVolume)
                {
                    maxConversion = remainingVolume / resultsToVolume / totalResults;
                }

                // Remove ingredients
                for (var i = 0; i < moles.Length; i++)
                {
                    container.RemoveSubstance(ingredientSubstances[i], maxConversion * (recipe.Ingredients[i].RelativeAmount / totalIngredients));
                }

                // Add results
                foreach (var component in recipe.Results)
                {
                    container.AddSubstance(FromId(component.Id), maxConversion * (component.RelativeAmount / totalResults));
                }

                container.MarkDirty();
            }
        }