Example #1
0
        /// <summary>
        /// Aggregates one or more recipes into a set of aggregated ingredients.  This is normally used to create a list of items needed to buy for multiple recipes without having to create a shopping list.
        /// </summary>
        /// <param name="recipeIds">A list of recipe IDs to aggregate.</param>
        /// <returns>A list of IngredientAggregation objects, one per unique ingredient in the set of recipes</returns>
        public virtual IList <IngredientAggregation> AggregateRecipes(params Guid[] recipeIds)
        {
            using (InitLock.ReadLock())
            {
                var ings = new Dictionary <Guid, IngredientAggregation>(); //List of all ingredients and total usage

                foreach (var id in recipeIds)
                {
                    //Lookup ingredient through modeler cache
                    var rNode = modeler.FindRecipe(id);
                    if (rNode == null) //Our cache is out of date, skip this result
                    {
                        continue;
                    }

                    foreach (var usage in rNode.Ingredients)
                    {
                        var ingId   = usage.Ingredient.IngredientId;
                        var ingName = ingParser.GetIngredientById(ingId);
                        var ing     = new Ingredient(ingId, ingName);
                        ing.ConversionType = usage.Ingredient.ConvType;

                        IngredientAggregation agg;
                        if (!ings.TryGetValue(ingId, out agg))
                        {
                            ings.Add(ingId, agg = new IngredientAggregation(ing)
                            {
                                Amount = new Amount(0, usage.Unit)
                            });
                        }

                        //TODO: If usage.Unit is different than agg.Amount.Unit then we have a problem, throw an exception if that happens?
                        if (agg.Amount == null) //This aggregation contains an empty amount, so we can't aggregate
                        {
                            continue;
                        }
                        else if (!usage.Amt.HasValue) //This amount is null, cancel aggregation
                        {
                            agg.Amount = null;
                        }
                        else
                        {
                            agg.Amount += usage.Amt.Value;
                        }
                    }
                }

                return(ings.Values.ToList());
            }
        }
Example #2
0
        /// <summary>
        /// Converts a usage of an ingredient within a recipe to an IngredientAggregation object, suitable for aggregating with other usages of the same ingredient.
        /// </summary>
        /// <param name="usage">An IngredientUsage object, usually from a recipe.</param>
        /// <returns>An IngredientAggregation object, usually to be combined with other uses of that ingredient to form a shopping list.</returns>
        public virtual IngredientAggregation ConvertIngredientUsage(IngredientUsage usage)
        {
            //TODO: Does this method need to be part of the context?  Perhaps IngredientUsage should have a method to convert to an aggregation

            var ing = ReadIngredient(usage.Ingredient.Id);

            if (ing == null)
            {
                throw new IngredientNotFoundException();
            }

            var a = new IngredientAggregation(ing);

            a.AddUsage(usage);

            return(a);
        }