/// <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 ingredient = this.ReadIngredient(usage.Ingredient.Id); if (ingredient == null) { throw new IngredientNotFoundException(); } var aggregation = new IngredientAggregation(ingredient); aggregation.AddUsage(usage); return aggregation; }
/// <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 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; }
/// <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 ingredients = new Dictionary<Guid, IngredientAggregation>(); // List of all ingredients and total usage foreach (var id in recipeIds) { // Lookup ingredient through modeler cache var recipeNode = this.modeler.FindRecipe(id); if (recipeNode == null) { // Our cache is out of date, skip this result continue; } foreach (var usage in recipeNode.Ingredients) { var ingredientId = usage.Ingredient.IngredientId; string ingredientName = this.ingredientParser.GetIngredientById(ingredientId); var ingredient = new Ingredient(ingredientId, ingredientName); ingredient.ConversionType = usage.Ingredient.ConversionType; IngredientAggregation aggregation; if (!ingredients.TryGetValue(ingredientId, out aggregation)) { aggregation = new IngredientAggregation(ingredient) { Amount = new Amount(0, usage.Unit) }; ingredients.Add(ingredientId, aggregation); } // TODO: If usage.Unit is different than agg.Amount.Unit then we have a problem, throw an exception if that happens? if (aggregation.Amount == null) { // This aggregation contains an empty amount, so we can't aggregate continue; } else if (!usage.Amount.HasValue) { // This amount is null, cancel aggregation aggregation.Amount = null; } else { aggregation.Amount += usage.Amount.Value; } } } return ingredients.Values.ToList(); } }
/// <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 IList<IngredientAggregation> AggregateRecipes(params Guid[] recipeIds) { 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 = ModelerProxy.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(); }