ProductOpener::Food - functions related to food products and nutrition
ProductOpener::Food
contains functions specific to food products,
in particular related to nutrition facts.
This module provides functions It does not contain functions related to ingredients which are in the ProductOpener::Ingredients
module.
..
Each nutrient value is entered as a string (by users on the product edit form, or through the API). The string value may not always be numeric (e.g. it can include a < sign).
This function normalizes the string value to remove signs, and stores extra information in the "modifier" field.
Input string value reference. The value will be normalized.
Output modifier reference.
- 0 if the input value indicates traces - Number (as a string) - undef for 'NaN' (not a number, sometimes sent by broken API clients)
<, >, ≤, ≥, ~ character sign, for lesser, greater, lesser or equal, greater or equal, and about - (minus sign) character when the input value is - (or other dashes) : indicates that the value is not present on the package
Return the default unit that we convert everything to internally
$nid: String
Default value for that certain unit
Assign a value with a unit and an optional modifier (< or ~) to a nutrient in the nutriments structure.
Nutrient id, possibly suffixed with "_prepared"
An array that condition how nutrients are displayed.
It is a list of nutrients names with eventual prefixes and suffixes:
#nutrient
a leading #
indicates a comment and will be ignored!nutrient
a leading !
indicates an important nutrient,
they should always be shownnutrient
- no dash for top nutrients-sub-nutrient
- for level 2--sub-sub-nutrient
- for level 3,
etc.nutrient-
a -
at the end indicates that the nutrient should be hidden and only shown if explicitly added.Canonicalizes the nutrients input by the user in the nutrition table product edit. This sub converts these nutrients (which are arguments to this function), into a recognizable/standard form.
Two strings are passed, $target_lc: The language in which the nutriment is (example: "en", "fr") $nutrient: The nutrient that needs to be canonicalized. (the user input nutrient, example: "AGS", "unsaturated-fat")
Returns the $nid (a string)
Example: For the parameter "dont saturés", we get the $nid as "saturated fat"
Determines if a product should be considered as a beverage for Nutri-Score computations, based on the product categories.
2021 Nutri-Score: Dairy drinks are not considered as beverages if they have at least 80% of milk.
Determines if a product should be considered as a beverage for Nutri-Score computations, based on the product categories.
2023 Nutri-Score: Milk and dairy drinks are considered beverages.
Determines if a product should be considered as water for Nutri-Score computations, based on the product categories.
Determines if a product should be considered as cheese for Nutri-Score computations, based on the product categories.
Determines if a product should be considered as fat for Nutri-Score (2021 version) computations, based on the product categories.
Determines if a product should be considered as fats / oils / nuts / seeds for Nutri-Score (2023 version) computations, based on the product categories.
From the 2022 main algorithm report update FINAL:
"This category includes fats and oils from plant or animal sources, including cream, margarines, butters and oils (as the current situation).
Additionally, the following products are included in this category, using the Harmonized System Nomenclature1 codes: - Nuts: 0801 0802 - Processed nuts: 200811 200819 - Ground nuts: 1202 - Seeds: 1204 (linseed) 1206 (sunflower)1207 (other seeds)
Of note chestnuts are excluded from the category."
Determines if a product should be considered as red meat for Nutri-Score (2023 version) computations, based on the product categories and/or ingredients.
From the 2022 main algorithm report update FINAL:
"Regarding the Codex Alimentarius classifications, the entire group 08.0 (Meat and meat products, including poultry and game and all its subgroups) is concerned, though not all food items in the individual sub-groups are concerned, only those containing red meat (see above). In the Harmonized System Classification, the codes correspond to the following:
Beef: o 0201 Meat of bovine animals, fresh or chilled o 0202 Meat of bovine animals, frozen Pork o 0203 Meat of swine, fresh, chilled or frozen Lamb: o 0204 Meat of sheep or goats, fresh, chilled or frozen Horse o 0205 Horse and equine meat Game and venison o 0208903000 Of game, other than of rabbits or hares o 02089060 Fresh, chilled or frozen reindeer meat and edible offal thereof Offals and processed meat (as red meat) o 0206 Edible offal of bovine animals, swine, sheep, goats, horses, asses, mules or hinnies, fresh, chilled or frozen o 0210 Meat and edible offal, salted, in brine, dried or smoked; edible flours and meals of meat or meat offal o 1601 sausages o 1602 Prepared or preserved meat, meat offal, blood or insects (excl. sausages and similar products, and meat extracts and juices) ▪ All those from swine, lamb or beef even as mixtures"
Compute the fruit % according to the Nutri-Score rules
<b>Warning</b> Also modifies product_ref->{misc_tags}
The fruit ratio
Compute the % of fruits, vegetables and legumes for the Nutri-Score 2023 algorithm.
Differences with the 2021 version: - we use only the estimate from the ingredients or a conservative estimate from the product category - we do not use values estimated by users from ingredients list: too difficult to know what should be included or not
Return undef if no value could be computed or estimated.
Compute saturated_fat_ratio as needed for nutriscore
Reference to either the "nutriments" or "nutriments_estimated" structure.
Detect if we are in the special case where we can detect saturated fat is 0 because fat is 0
Reference to either the "nutriments" or "nutriments_estimated" structure.
Detect if we are in the special case where we can detect sugars are 0 because carbohydrates are 0
Reference to either the "nutriments" or "nutriments_estimated" structure.
Compute data for nutriscore computation.
<b>Warning:</b> it also modifies $product_ref
Reference to either the "nutriments" or "nutriments_estimated" structure.
Ref to a mapping suitable to call compute_nutriscore_score_and_grade
Check that the product has a category, that we know if it is a beverage or not, and that it is not in a category for which the Nutri-Score should not be computed (e.g. food for babies)
Check if the product should have prepared nutrition data, based on its categories.
Return the product category tag that should have prepared nutrition data, or undef if none.
Check that we know or can estimate the nutrients needed to compute the Nutri-Score of the product.
Suffix to indicate if the Nutri-Score should be computed on prepared values
Indicates which nutrients fields were used to compute the Nutri-Score.
We may compute several versions of the Nutri-Score grade and score. One version is considered "current". This function sets the product fields for the current version.
When we are migrating from one version of the Nutri-Score to another (e.g. 2021 vs 2023), we may compute both version for a time. This function sets temporary fields to ease the comparison of both versions.
Once the migration is complete, those fields will no longer be computed.
Determines if we have enough data to compute the Nutri-Score (category + nutrition facts), and if the Nutri-Score is applicable to the product the category.
Populates the data structure needed to compute the Nutri-Score and computes it.
Input nutrition data is indicated per 100g or per serving. This function computes the nutrition data for the other quantity (per serving or per 100g) if we know the serving quantity.
create_nutrients_level_taxonomy()
creates the source file for the nutrients level taxonomy: /taxonomies/nutrient_levels.txt
It creates entries such as "High in saturated fat" in all languages.
calculate the number of units of alcohol in one serving of an alcoholic beverage. (https://en.wikipedia.org/wiki/Unit_of_alcohol)
Go through the categories of a product to apply category properties at the product level. The most specific categories are checked first. If the category has a value for the property, it is assigned to the product and the processing stop.
This function was first designed to assign a CIQUAL category to products, based on the mapping of the Open Food Facts categories to the French CIQUAL categories.
It may be used for other properties in the future.
agribalyse_food_code:en:42501 agribalyse_proxy_food_code:en:43244
This function reads the nutriment values passed to the product edit form, or the product edit API, and assigns them to the product.
Compute estimated nutrients from ingredients.
If we have a high enough confidence (95% of the ingredients (by quantity) have a known nutrient profile), we store the result in the nutriments_estimated hash.
Returns the unit of the nutrient.
We may have a unit specific to the country (e.g. US nutrition facts table using the International Unit for this nutrient, and Europe using mg)