public ShoppingListAddAction AddUsage(IngredientUsage usage) { adder.Usages.Add(usage); return(this); }
public IngredientAdder AddIngredient(Ingredient ingredient, Amount amount, string prepNote = null) { var usage = new IngredientUsage(ingredient, null, amount, prepNote); return(AddIngredientUsage(usage)); }
public IngredientUsageCreator(IngredientUsage usage) { this.Usage = usage; }
public static Amount GetNativeAmountForUsage(Ingredient ingredient, IngredientUsage usage) { var amount = new Amount(); var usageConvType = Unit.GetConvType(usage.Form.FormUnitType); switch (ingredient.ConversionType) //This is the type we must convert to { case UnitType.Unit: amount.Unit = Units.Unit; if (usageConvType == UnitType.Unit) //Unit to unit version { var equivGrams = UnitConverter.Convert(usage.Form.FormAmount, Units.Gram); //Grams this form is equivelent to amount.SizeHigh = (float)Math.Ceiling((equivGrams.SizeHigh * usage.Amount.SizeHigh) / ingredient.UnitWeight); return(amount); } if (usageConvType == UnitType.Weight) //Weight to unit conversion { var grams = UnitConverter.Convert(usage.Amount, Units.Gram); amount.SizeHigh = (float)Math.Ceiling(grams.SizeHigh / ingredient.UnitWeight); return(amount); } if (usageConvType == UnitType.Volume) //Volume to unit conversion { var likeAmount = UnitConverter.Convert(usage.Amount, usage.Form.FormUnitType); amount.SizeHigh = (float)Math.Ceiling((likeAmount.SizeHigh * usage.Form.FormAmount.SizeHigh) / usage.Ingredient.UnitWeight); //Round up when dealing with whole units return(amount); } break; case UnitType.Weight: amount.Unit = Units.Gram; if (usageConvType == UnitType.Unit) //Unit to weight conversion { amount.SizeHigh = usage.Amount.SizeHigh * usage.Form.FormAmount.SizeHigh; //NOTE: FormAmount will always be in Grams when Ingredient ConvType is weight return(amount); } if (usageConvType == UnitType.Volume) //Volume to weight conversion { var likeAmount = UnitConverter.Convert(usage.Amount, usage.Form.FormUnitType); amount.SizeHigh = likeAmount.SizeHigh * usage.Form.FormAmount.SizeHigh; //NOTE: FormAmount will always be in Grams when Ingredient ConvType is weight return(amount); } break; case UnitType.Volume: amount.Unit = Units.Teaspoon; if (usageConvType == UnitType.Unit) //Unit to volume conversion { amount.SizeHigh = usage.Amount.SizeHigh * usage.Form.FormAmount.SizeHigh; //NOTE: FormAmount will always be in tsp when Ingredient ConvType is volume return(amount); } if (usageConvType == UnitType.Weight) //Weight to volume conversion { var likeAmount = UnitConverter.Convert(usage.Amount, usage.Form.FormUnitType); amount.SizeHigh = likeAmount.SizeHigh * usage.Form.FormAmount.SizeHigh; //NOTE: FormAmount will always be in teaspoons when Ingredient ConvType is Volume return(amount); } break; } //throw new IngredientAggregationDatabaseException("Cannot convert an IngredientUsage into its native form.", ingredient, usage); throw new Exception("Cannot convert an IngredientUsage into its native form."); }
public void AddIngredient(IngredientUsage ingredient) { _ingredients.Add(ingredient); }
public AnomalousMatch(string input, AnomalousResult anomaly, IngredientUsage usage) : base(input, usage) { this.anomaly = anomaly; }
/// <summary>Assembles a Result baesd on NLP match data for a given template.</summary> /// <param name="template">A passing NLP template that yieled match data</param> /// <param name="input">The original input string that was parsed</param> /// <param name="matchdata">Match data generated from the specified NLP template</param> /// <returns>Result describing the generated KitchenPC IngredientUsage or error code if usage could not be generated</returns> public static Result BuildResult(Template template, string input, MatchData matchdata) { var result = new IngredientUsage(); var ingName = (matchdata.Ingredient.Parent == null) ? matchdata.Ingredient.IngredientName : matchdata.Ingredient.Parent.IngredientName; result.Ingredient = new Ingredient(matchdata.Ingredient.Id, ingName); result.Ingredient.ConversionType = matchdata.Ingredient.ConversionType; result.Ingredient.UnitWeight = matchdata.Ingredient.UnitWeight; result.Amount = matchdata.Amount; result.PreparationNote = matchdata.Preps.HasValue ? matchdata.Preps.ToString() : template.DefaultPrep; var pairings = matchdata.Ingredient.Pairings; NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Ingredient: {0}", matchdata.Ingredient.IngredientName); if (matchdata.Ingredient.Parent != null) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Re-Link to Root Ingredient: {0}", matchdata.Ingredient.Parent.IngredientName); } if (template.AllowPartial && matchdata.Amount == null) { return new PartialMatch(input, result.Ingredient, result.PreparationNote); } if (matchdata.Unit is CustomUnitNode) { IngredientForm form; if (UnitSynonyms.TryGetFormForIngredient(matchdata.Unit.Name, matchdata.Ingredient.Id, out form)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Based on unit name {0}, linking to form id {1}", matchdata.Unit.Name, form.FormId); result.Form = form; } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Unable to find link between unit '{0}' and ingredient '{1}'.", matchdata.Unit.Name, result.Ingredient.Name); return new NoMatch(input, MatchResult.UnknownUnit); } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No custom unit found, so cannot get form based on unit."); } if (matchdata.Form != null) { IngredientForm form; if (FormSynonyms.TryGetFormForIngredient(matchdata.Form.FormName, matchdata.Ingredient.Id, out form)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Based on reference to form {0}, linking to form id {1}", matchdata.Form.FormName, form.FormId); result.Form = form; } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Unable to find link between form '{0}' and ingredient '{1}.", matchdata.Form.FormName, result.Ingredient.Name); return new NoMatch(input, MatchResult.UnknownForm); } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No known form found, so cannot get form based on form synonym."); } if (result.Form == null) { if (matchdata.Unit == null || matchdata.Unit.Unit == Units.Unit) // TODO: Is second part necessary? Only Units.Unit would be custom form types, and we'd have errored out already if that didn't match { result.Form = pairings.Unit; NlpTracer.ConditionalTrace(pairings.HasUnit, TraceLevel.Debug, "[BuildResult] Linking to default Unit paired form {0}", pairings.Unit); } else { switch (Unit.GetConvertionType(matchdata.Unit.Unit)) { case UnitType.Volume: result.Form = pairings.Volume; NlpTracer.ConditionalTrace(pairings.HasVolume, TraceLevel.Debug, "[BuildResult] Linking to default paired Volume form {0}", pairings.Volume); break; case UnitType.Weight: result.Form = pairings.Weight; NlpTracer.ConditionalTrace(pairings.HasWeight, TraceLevel.Debug, "[BuildResult] Linking to default paired Weight form {0}", pairings.Weight); break; } } if (result.Form == null && result.Amount.Unit == Units.Ounce && pairings.HasVolume) { result.Form = pairings.Volume; result.Amount.Unit = Units.FluidOunce; NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Interpretting reference to Ounces as Fluid Ounces and linking to volumetric form {0}", pairings.Volume); } if (result.Form == null) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Could not find any default pairing for the unit type: {0}", result.Amount.Unit); } } var parsedType = Unit.GetConvertionType(result.Amount.Unit); if (result.Form != null && parsedType == Unit.GetConvertionType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Info, "[BuildResult] SUCCESS: Linked form is compatible with usage reference."); return new Match(input, result); } NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Running anomalous parsing."); // TODO: If matchdata has multiple prep notes, we either need to only parse the user entered one or avoid duplicate matches if (parsedType == UnitType.Volume && matchdata.Preps.HasValue) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Checking for form matching prep note: {0}", matchdata.Preps); IngredientForm form; if (FormSynonyms.TryGetFormForPrep(matchdata.Preps, matchdata.Ingredient, true, out form)) { result.Form = form; if (parsedType == Unit.GetConvertionType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Found matching volumetric form, allowing prep to form fall-through."); result.PreparationNote = matchdata.Preps.ToString(); return new AnomalousMatch(input, AnomalousResult.Fallthrough, result); } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Found matching form, but form is not compatible with volumetric usage."); } } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Could not clarify form through prep note, since unit type is not volumetric or there is no prep note."); } if (result.Form != null) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Form and unit incompatible - attempting to auto-convert form {0}", result.Form); var formType = Unit.GetConvertionType(result.Form.FormUnitType); if (parsedType == UnitType.Weight && formType == UnitType.Volume && pairings.HasWeight) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default weight pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PreparationNote = result.Form.FormDisplayName; result.Form = pairings.Weight; return new AnomalousMatch(input, AnomalousResult.AutoConvert, result); } else if (parsedType == UnitType.Unit && formType == UnitType.Volume) { if (pairings.HasUnit && (matchdata.Unit == null || string.IsNullOrEmpty(matchdata.Unit.Name))) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default unit pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PreparationNote = result.Form.FormDisplayName; result.Form = pairings.Unit; return new AnomalousMatch(input, AnomalousResult.AutoConvert, result); } if (matchdata.Unit != null && false == string.IsNullOrEmpty(matchdata.Unit.Name)) { IngredientForm form; NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Attempting to convert volumetric usage to unit form for custom unit: {0}", matchdata.Unit.Name); if (UnitSynonyms.TryGetFormForIngredient(matchdata.Unit.Name, matchdata.Ingredient.Id, out form)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to custom unit pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PreparationNote = result.Form.FormDisplayName; result.Form = form; return new AnomalousMatch(input, AnomalousResult.AutoConvert, result); } } } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Could not auto-convert form since there is no form to convert."); } if (result.Form == null) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could still not find a form for this usage."); return new NoMatch(input, MatchResult.NoForm); } NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could not fix form/unit incompatibility."); return new NoMatch(input, MatchResult.IncompatibleForm); }
public void TestFormConverter() { //Form conversions (Unit ingredients) var unitIng = new Ingredient() { ConversionType = UnitType.Unit, UnitWeight = 200 }; //Ingredient sold by units (unit weighs 200g) var unitIng_UnitForm = new IngredientForm() { FormAmount = new Amount(50, Units.Gram), ConversionMultiplier = 1, FormUnitType = Units.Unit }; //Form expressed in units (unit in this form weighs 50g) var unitIng_WeightForm = new IngredientForm() { ConversionMultiplier = 1, FormUnitType = Units.Ounce }; //Form expressed by weight var unitIng_VolForm = new IngredientForm() { FormUnitType = Units.Cup, ConversionMultiplier = 1, FormAmount = new Amount(20, Units.Gram) }; //Each cup weighs 20g) var unitIng_UnitUsage = new IngredientUsage() { Amount = new Amount(4, Units.Unit), Form = unitIng_UnitForm, Ingredient = unitIng }; var unitIng_WeightUsage = new IngredientUsage() { Amount = new Amount(300, Units.Gram), Form = unitIng_WeightForm, Ingredient = unitIng }; var unitIng_VolUsage = new IngredientUsage() { Amount = new Amount(160, Units.Tablespoon), Form = unitIng_VolForm, Ingredient = unitIng }; //10 cups var unitIng_UnitAmt = FormConversion.GetNativeAmountForUsage(unitIng, unitIng_UnitUsage); var unitIng_WeightAmt = FormConversion.GetNativeAmountForUsage(unitIng, unitIng_WeightUsage); var unitIng_VolAmt = FormConversion.GetNativeAmountForUsage(unitIng, unitIng_VolUsage); Assert.AreEqual(1.0f, unitIng_UnitAmt.SizeHigh); //4 units in this form should convert to 1 unit of ingredient Assert.AreEqual(Units.Unit, unitIng_UnitAmt.Unit); Assert.AreEqual(2.0f, unitIng_WeightAmt.SizeHigh); //300g of this form should convert to 1.5 units of ingredient, however we round up to whole units Assert.AreEqual(Units.Unit, unitIng_WeightAmt.Unit); //TODO: Fix //Assert.AreEqual(1.0f, unitIng_VolAmt.SizeHigh); //10 cups of this form should convert to 1 unit of ingredient //Assert.AreEqual(Units.Unit, unitIng_VolAmt.Unit); //Form conversions (Volume ingredients) var volIng = new Ingredient() { ConversionType = UnitType.Volume }; //Ingredient sold by volume var volIng_UnitForm = new IngredientForm() { FormUnitType = Units.Unit, ConversionMultiplier = 1, FormAmount = new Amount(5, Units.Teaspoon) }; var volIng_WeightForm = new IngredientForm() { FormUnitType = Units.Ounce, ConversionMultiplier = 1, FormAmount = new Amount(2, Units.Teaspoon) }; var volIng_UnitUsage = new IngredientUsage() { Amount = new Amount(2, Units.Unit), Form = volIng_UnitForm, Ingredient = volIng }; var volIng_WeightUsage = new IngredientUsage() { Amount = new Amount(0.25f, Units.Pound), Form = volIng_WeightForm, Ingredient = volIng }; //4oz var volIng_UnitAmt = FormConversion.GetNativeAmountForUsage(volIng, volIng_UnitUsage); var volIng_WeightAmt = FormConversion.GetNativeAmountForUsage(volIng, volIng_WeightUsage); Assert.AreEqual(10.0f, volIng_UnitAmt.SizeHigh); Assert.AreEqual(Units.Teaspoon, volIng_UnitAmt.Unit); Assert.AreEqual(8.0f, volIng_WeightAmt.SizeHigh); Assert.AreEqual(Units.Teaspoon, volIng_WeightAmt.Unit); //Form conversions (Weight ingredients) var weightIng = new Ingredient() { ConversionType = UnitType.Weight }; //Ingredient sold by weight var weightIng_UnitForm = new IngredientForm() { ConversionMultiplier = 1, FormUnitType = Units.Unit, FormAmount = new Amount(100, Units.Gram) }; var weightIng_VolForm = new IngredientForm() { ConversionMultiplier = 1, FormUnitType = Units.Cup, FormAmount = new Amount(50, Units.Gram) }; var weightIng_UnitUsage = new IngredientUsage() { Amount = new Amount(5, Units.Unit), Form = weightIng_UnitForm, Ingredient = weightIng }; var weightIng_VolUsage = new IngredientUsage() { Amount = new Amount(144, Units.Teaspoon), Form = weightIng_VolForm, Ingredient = weightIng }; //3 cups var weightIng_UnitAmt = FormConversion.GetNativeAmountForUsage(weightIng, weightIng_UnitUsage); var weightIng_VolAmt = FormConversion.GetNativeAmountForUsage(weightIng, weightIng_VolUsage); Assert.AreEqual(500.0f, weightIng_UnitAmt.SizeHigh); Assert.AreEqual(Units.Gram, weightIng_UnitAmt.Unit); Assert.AreEqual(150.0f, weightIng_VolAmt.SizeHigh); Assert.AreEqual(Units.Gram, weightIng_VolAmt.Unit); }
public Match(string input, IngredientUsage usage) : base(input) { this.usage = usage; }