/// <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(); //Use this to hold partial matching data, but throw away if not a complete match. 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.PrepNote = 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) //No amount, any forms are now irrelevant { return new PartialMatch(input, result.Ingredient, result.PrepNote); } //If we parsed a custom unit (heads of lettuce), check if there's a mapping for that unit name to the ingredient and use that form 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); //User specified a custom form that is not in any way linked to this ingredient, this is an error condition } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No custom unit found, so cannot get form based on unit."); } //If we parsed a form alias (shredded), lookup the FormID from the formname/ingredient map (will override unit alias) 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); //User specified a form that is not in any way linked to this ingredient, this is an error condition } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No known form found, so cannot get form based on form synonym."); } if (result.Form == null) //Load default form for parsed unit type { 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.GetConvType(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) //Try as FluidOunces because so many recipes use oz when they mean fl oz { 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); } } //If we've loaded a form type and they're compatible, return match var parsedType = Unit.GetConvType(result.Amount.Unit); if (result.Form != null && parsedType == Unit.GetConvType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Info, "[BuildResult] SUCCESS: Linked form is compatible with usage reference."); return new Match(input, result); } // ************************** // *** ANOMALOUS PARSING **** // ************************** NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Running anomalous parsing."); // Prep to form fall-through: Allow prep to clarify form with volumetric usages if no default pairing is known, eg: 3 cups apples, chopped --> apples (chopped) : 3 cups // 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.GetConvType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Found matching volumetric form, allowing prep to form fall-through."); result.PrepNote = 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."); } // Auto Form Conversion: If we can make a valid assumption about a form even if unit type is incompatible, we can convert to another form, eg: 5oz shredded cheese --> cheese: 5oz (shredded) if (result.Form != null) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Form and unit incompatible - attempting to auto-convert form {0}", result.Form); var formType = Unit.GetConvType(result.Form.FormUnitType); if (parsedType == UnitType.Weight && formType == UnitType.Volume && pairings.HasWeight) //Something like 3oz shredded cheddar cheese, we need to use a weight form and set prep note { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default weight pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PrepNote = result.Form.FormDisplayName; result.Form = pairings.Weight; return new AnomalousMatch(input, AnomalousResult.AutoConvert, result); } else if (parsedType == UnitType.Unit && formType == UnitType.Volume) //Something like 3 mashed bananas { if (pairings.HasUnit && (matchdata.Unit == null || String.IsNullOrEmpty(matchdata.Unit.Name))) //No custom unit, just use default pairing { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default unit pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PrepNote = result.Form.FormDisplayName; result.Form = pairings.Unit; return new AnomalousMatch(input, AnomalousResult.AutoConvert, result); } if (matchdata.Unit != null && false == String.IsNullOrEmpty(matchdata.Unit.Name)) //We have a custom unit { 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.PrepNote = 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."); } //Error out if (result.Form == null) //Still have not found a form, we give up now { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could still not find a form for this usage."); return new NoMatch(input, MatchResult.NoForm); //No default form pairings, so return NoForm } NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could not fix form/unit incompatibility."); return new NoMatch(input, MatchResult.IncompatibleForm); }
/// <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(); //Use this to hold partial matching data, but throw away if not a complete match. 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.PrepNote = 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) //No amount, any forms are now irrelevant { return new PartialMatch(input, result.Ingredient, result.PrepNote); } //If we parsed a custom unit (heads of lettuce), check if there's a mapping for that unit name to the ingredient and use that form if (matchdata.Unit is CustomUnitNode) { Result noMatch; bool hasReturned = ProcessCustimUnitNode(input, matchdata, result, out noMatch); if (hasReturned) { return noMatch; } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No custom unit found, so cannot get form based on unit."); } //If we parsed a form alias (shredded), lookup the FormID from the formname/ingredient map (will override unit alias) if (matchdata.Form != null) { Result MatchDataFormResult; bool hasReturned = ProcessMatchDataNullForm(input, matchdata, result, out MatchDataFormResult); if (hasReturned) { return MatchDataFormResult; } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] No known form found, so cannot get form based on form synonym."); } if (result.Form == null) //Load default form for parsed unit type { LoadDefaultForm(matchdata, result, pairings); } //If we've loaded a form type and they're compatible, return match var parsedType = Unit.GetConvType(result.Amount.Unit); if (result.Form != null && parsedType == Unit.GetConvType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Info, "[BuildResult] SUCCESS: Linked form is compatible with usage reference."); return new Match(input, result); } // ************************** // *** ANOMALOUS PARSING **** // ************************** NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Running anomalous parsing."); // Prep to form fall-through: Allow prep to clarify form with volumetric usages if no default pairing is known, eg: 3 cups apples, chopped --> apples (chopped) : 3 cups // 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) { Result anomalousMatch; bool hasReturned = ProcessAnomalousMatch(input, matchdata, result, parsedType, out anomalousMatch); if (hasReturned) { return anomalousMatch; } } 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."); } // Auto Form Conversion: If we can make a valid assumption about a form even if unit type is incompatible, we can convert to another form, eg: 5oz shredded cheese --> cheese: 5oz (shredded) if (result.Form != null) { Result AutoConversionResult; bool wasConverted = AutoFormConvert(input, matchdata, result, parsedType, pairings, out AutoConversionResult); if (wasConverted) { return AutoConversionResult; } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Could not auto-convert form since there is no form to convert."); } //Error out if (result.Form == null) //Still have not found a form, we give up now { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could still not find a form for this usage."); return new NoMatch(input, MatchResult.NoForm); //No default form pairings, so return NoForm } NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] ERROR: Anomalous parsing could not fix form/unit incompatibility."); return new NoMatch(input, MatchResult.IncompatibleForm); }
/// <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); }
private static bool ProcessMatchDataNullForm(string input, MatchData matchdata, IngredientUsage result, out Result buildResultNullForm) { 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); { buildResultNullForm = new NoMatch(input, MatchResult.UnknownForm); return true; } } buildResultNullForm = null; return false; }
private static bool ProcessCustimUnitNode(string input, MatchData matchdata, IngredientUsage result, out Result noMatch) { 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); { noMatch = new NoMatch(input, MatchResult.UnknownUnit); return true; } } noMatch = null; return false; }
private static bool ProcessAnomalousMatch(string input, MatchData matchdata, IngredientUsage result, UnitType parsedType, out Result anomalousMatch) { 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.GetConvType(result.Form.FormUnitType)) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Found matching volumetric form, allowing prep to form fall-through."); result.PrepNote = matchdata.Preps.ToString(); { anomalousMatch = new AnomalousMatch(input, AnomalousResult.Fallthrough, result); return true; } } else { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Found matching form, but form is not compatible with volumetric usage."); } } anomalousMatch = null; return false; }
private static void LoadDefaultForm(MatchData matchdata, IngredientUsage result, DefaultPairings pairings) { 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.GetConvType(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) //Try as FluidOunces because so many recipes use oz when they mean fl oz { 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); } }
private static bool AutoFormConvert(string input, MatchData matchdata, IngredientUsage result, UnitType parsedType, DefaultPairings pairings, out Result autoConvertResult) { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] Form and unit incompatible - attempting to auto-convert form {0}", result.Form); var formType = Unit.GetConvType(result.Form.FormUnitType); if (parsedType == UnitType.Weight && formType == UnitType.Volume && pairings.HasWeight) //Something like 3oz shredded cheddar cheese, we need to use a weight form and set prep note { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default weight pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PrepNote = result.Form.FormDisplayName; result.Form = pairings.Weight; { autoConvertResult = new AnomalousMatch(input, AnomalousResult.AutoConvert, result); return true; } } else if (parsedType == UnitType.Unit && formType == UnitType.Volume) //Something like 3 mashed bananas { if (pairings.HasUnit && (matchdata.Unit == null || String.IsNullOrEmpty(matchdata.Unit.Name))) //No custom unit, just use default pairing { NlpTracer.Trace(TraceLevel.Debug, "[BuildResult] SUCCESS: Converting to default unit pairing, and setting prep note to: {0}", result.Form.FormDisplayName); result.PrepNote = result.Form.FormDisplayName; result.Form = pairings.Unit; { autoConvertResult = new AnomalousMatch(input, AnomalousResult.AutoConvert, result); return true; } } if (matchdata.Unit != null && false == String.IsNullOrEmpty(matchdata.Unit.Name)) //We have a custom unit { 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.PrepNote = result.Form.FormDisplayName; result.Form = form; { autoConvertResult = new AnomalousMatch(input, AnomalousResult.AutoConvert, result); return true; } } } } autoConvertResult = null; return false; }