From cdd7cf5f14c4ac82704da4921c9b05bd7582dac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Gigandet?= Date: Thu, 9 Jan 2025 11:27:25 +0100 Subject: [PATCH] fix: Nutriscore for fresh herbs (#11112) Fresh herbs need to be included in fruits/vegetables/legumes from FAQ-updatedAlgo-EN_20240626.pdf: ``` The detailed list of the various foods qualifying in this component is available in Appendix 2. The foods included in the following groups from the Eurocode 2 classification10 (in English) can be taken into account for the calculation of the component: - In both the Original and the Updated Algorithms: i. Group 7.10 (Pulses) (i.e. Legumes); ii.Group 8.10 (Leaf vegetables); 8.15 (Brassicas); 8.20 (Stalk vegetables); 8.25 (Shoot vegetables); 8.30 (Onion-family vegetables); 8.38 (Root vegetables); 8.40 (Fruit vegetables); 8.45 (Seed vegetables and immature pulses); 8.50 (Edible fungi); 8.55 (Seaweeds and algae); 8.60 (Vegetable mixtures) iii Group 9.10 (Malaceous fruit); 9.20 (Prunus species fruit); 9.25 (Other stone fruit); 9.30 (Berries); 9.40 (Citrus fruit); 9.50 (Miscellaneous fruit); 9.60 (Fruit mixtures). iv Group 12.20 (Herbs) ``` --- lib/ProductOpener/Config_off.pm | 2 +- lib/ProductOpener/Ingredients.pm | 5 +- taxonomies/food/categories.txt | 4 +- taxonomies/food/ingredients.txt | 140 +++-- .../ingredients/fi-do-not-match-myanmar.json | 8 +- .../ingredients/fr-epices-irradiees.json | 8 +- .../nutriscore/en-dill.json | 427 ++++++++++++++ .../nutriscore/en-orange.json | 426 ++++++++++++++ .../nutriscore/honey.json | 142 ----- .../nutriscore/pl-pickled-vegetables.json | 530 ++++++++++++++++++ ...rgherita-pizzas.fr-margherita-pizza-1.json | 8 +- ...rgherita-pizza-2-compound-ingredients.json | 8 +- .../taxonomies/eurocodes.csv | 28 +- tests/unit/ingredients_nutriscore.t | 10 +- tests/unit/nutriscore.t | 39 ++ 15 files changed, 1577 insertions(+), 208 deletions(-) create mode 100644 tests/unit/expected_test_results/nutriscore/en-dill.json create mode 100644 tests/unit/expected_test_results/nutriscore/en-orange.json delete mode 100644 tests/unit/expected_test_results/nutriscore/honey.json create mode 100644 tests/unit/expected_test_results/nutriscore/pl-pickled-vegetables.json diff --git a/lib/ProductOpener/Config_off.pm b/lib/ProductOpener/Config_off.pm index 3203e05c0674a..a393db09a760d 100644 --- a/lib/ProductOpener/Config_off.pm +++ b/lib/ProductOpener/Config_off.pm @@ -603,11 +603,11 @@ $options{categories_considered_as_beverages_for_nutriscore_2023} = [ $options{categories_exempted_from_nutriscore} = [ qw( en:alcoholic-beverages - en:aromatic-herbs en:baby-foods en:baby-milks en:chewing-gum en:food-additives + en:dietary-supplements en:meal-replacements en:salts en:spices diff --git a/lib/ProductOpener/Ingredients.pm b/lib/ProductOpener/Ingredients.pm index b59e1447a9502..037c63e1f762b 100644 --- a/lib/ProductOpener/Ingredients.pm +++ b/lib/ProductOpener/Ingredients.pm @@ -8130,6 +8130,7 @@ can be taken into account, whereas crisps which are thin and completely dehydrat =cut my %fruits_vegetables_legumes_eurocodes = ( + "7.10" => 1, "8.10" => 1, "8.15" => 1, "8.20" => 1, @@ -8149,7 +8150,7 @@ my %fruits_vegetables_legumes_eurocodes = ( "9.40" => 1, "9.50" => 1, "9.60" => 1, - "7.10" => 1, + "12.20" => 1, # Herbs ); sub is_fruits_vegetables_legumes ($ingredient_id, $processing = undef) { @@ -8170,7 +8171,7 @@ sub is_fruits_vegetables_legumes ($ingredient_id, $processing = undef) { ((defined $eurocode_2_group_1) and ($eurocode_2_group_1 eq "9")) # Vegetables and legumes or ((defined $eurocode_2_group_2) - and (exists $fruits_vegetables_legumes_eurocodes{$eurocode_2_group_2})) + and ($fruits_vegetables_legumes_eurocodes{$eurocode_2_group_2})) ) and (not $is_a_further_processed_ingredient) and (not $further_processed) diff --git a/taxonomies/food/categories.txt b/taxonomies/food/categories.txt index f228589f17989..073488fabda37 100644 --- a/taxonomies/food/categories.txt +++ b/taxonomies/food/categories.txt @@ -116633,7 +116633,7 @@ nl: Eendterrine met morieljes < en:Duck terrines fr: Terrines de canard au muscat -en: Dietary supplements +en: Dietary supplements, food supplements af: Diëet aanvulling ar: مكمل غذائي bs: Prehrambeni suplement @@ -116647,7 +116647,7 @@ es: Suplementos dietéticos, Complementos alimenticios eu: Elikadura-osagarri fa: مکمل‌های غذایی طبیعی fi: Ravintolisät, Lisäravintoaine -fr: Compléments alimentaires +fr: Compléments alimentaires, complément alimentaire gl: Suplemento dietético he: תוספי תזונה hi: खाद्य पूरक diff --git a/taxonomies/food/ingredients.txt b/taxonomies/food/ingredients.txt index 391cbb7185750..9f72978ba44d8 100644 --- a/taxonomies/food/ingredients.txt +++ b/taxonomies/food/ingredients.txt @@ -41886,6 +41886,21 @@ de: Kaffirlimettenschale, Kaffirlimettenschalen, Kaffernlimettenschale es: piel de lima Kaffir hr: kora kafirske limete +< en: citrus fruit +en: bergamot +fr: bergamote + +< en: bergamot +en: bergamot leaf, bergamot leaves +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.16 + +< en: bergamot +en: bergamot flower +fr: fleur de bergamote, fleurs de bergamote +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.16 + < en:fruit en: kumquat, kumquats af: koemkwat @@ -45413,7 +45428,6 @@ vi: Củ khởi wikidata:en: Q2617260 wikipedia:en: https://en.wikipedia.org/wiki/Goji - < en:goji en: dried goji berries de: getrocknete Goji-Beeren @@ -51041,6 +51055,7 @@ ciqual_proxy_food_code:en: 11014 ciqual_proxy_food_name:en: Parsley, fresh ciqual_proxy_food_name:fr: Persil, frais # en:22363 in 51 @2021-09-16 +eurocode_2_group_2:en: 8.10 eurocode_2_group_3:en: 8.10.60 # aeb-arab:معدنوس # aeb-latn:ma3dnous @@ -52388,8 +52403,9 @@ ciqual_food_name:en: Fennel, raw ciqual_food_name:fr: Fenouil, cru ecobalyse:en: fennel-eu ecobalyse_origins_en_france:en: fennel-fr +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.34 # 2221 in20 @2021-10-09 -eurocode_2_group_3:en: 8.20.20 wikidata:en: Q43511 # aeb-arab:بسباس # ast:fenoyu @@ -52412,7 +52428,6 @@ wikidata:en: Q43511 # zh-tw:茴香 wikipedia:en: https://en.wikipedia.org/wiki/Fennel - < en:stalk vegetable en: sea kale, seakale, crambe es: col marina @@ -55860,10 +55875,13 @@ description:fr: La Bourrache ou Bourrache officinale (Borago officinalis) est un description:it: La borragine (Borago officinalis L.) è una pianta erbacea annuale della famiglia delle Boraginaceae. Le foglie giovani sono variamente impiegate in cucina. description:nl: De bernagie (Borago officinalis), ook vaak komkommerkruid genoemd, is een gemakkelijk herkenbare, ruwharige, eenjarige plant met blauwe bloemen. Als voedsel wordt de plant vooral in het Middellandse Zeegebied gewaardeerd als onderdeel van salades en andere zomerse gerechten. description:pt: Borragem (Borago officinalis L.), é uma planta herbácea anual mediterrânea. Folhas e flores são utilizadas. +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.20 wikidata:en: Q147075 wikipedia:en: https://en.wikipedia.org/wiki/Borage # 27 in 4 @2021-09-05 + < en:vegetable en: cardoon, artichoke thistle, cardoons ca: card @@ -60416,6 +60434,7 @@ uk: Адзукі vi: Đậu đỏ za: Lwglimz zh: 紅豆 +eurocode_2_group_2:en: 7.10 wikidata:en: Q380279 < en:legume @@ -64798,7 +64817,7 @@ da: urt, krydderurter de: Gewürz, Kräuter es: hierba, hierbas, plantas aromáticas, planta aromática, hierbas aromaticas, finas hierbas, mezcla de finas hierbas fi: yrtti, yrtit, mausteyrtit -fr: herbe, herbes, plantes aromatiques, plante aromatique, fines herbes, fine herbe, mélange de plantes aromatiques, herbes aromatiques +fr: herbe, herbes, plantes aromatiques, plante aromatique, fines herbes, fine herbe, mélange de plantes aromatiques, herbe aromatique, herbes aromatiques he: עשב hr: aromatskog bilja hu: gyógynövény, gyógynövények @@ -64811,6 +64830,8 @@ pt: plantas aromáticas ro: Ierburi, plante aromatice sl: zelišča sv: örter, örtkryddor, kryddörter +eurocode_2_group_2:en: 12.20 +nutriscore_fruits_vegetables_nuts:en: yes vegan:en: yes vegetarian:en: yes @@ -66203,6 +66224,9 @@ ur: میتھی vi: cỏ ca ri yi: באקסהארן zh: 胡芦巴 +# fr:fenugrec has 171 products in 5 languages @2018-10-23 +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.36 #ach:haleuba #arz:حلبة #azb:چمن اوْتو @@ -66216,7 +66240,6 @@ zh: 胡芦巴 #wuu:胡芦巴 wikidata:en: Q133205 wikipedia:en: https://en.wikipedia.org/wiki/Fenugreek -# fr:fenugrec has 171 products in 5 languages @2018-10-23 < en:fenugreek en: fenugreek leaf, fenugreek leaves @@ -66979,8 +67002,10 @@ sv: korianderblad ciqual_food_code:en: 11094 ciqual_food_name:en: Coriander, fresh ciqual_food_name:fr: Coriandre, fraiche -wikidata:en: Q65523167 # 4528 in 9 @2021-09-28 +eurocode_2_group_2:en: 12.20 +eurocode_2_group_3:en: 12.20.38 +wikidata:en: Q65523167 #processing:en: en:dried # "fr", - ingredients_text => - "Courgette grillée 37,5%, tomate pelée 20%, poivron jaune 17%, oignon rouge grillé 8%, eau, huile d'olive vierge extra 3,9%, oignon, olive noire entière dénoyautée saumurée 2,5% (olive, eau, sel, correcteurs d'acidité : acide citrique, acide lactique), ail, basilic 0,9%, amidon de riz, sel" + ingredients_text => "Courgette grillée 37,5%, tomate pelée 20%, poivron jaune 17%, oignon rouge grillé 8%, + eau, huile d'olive vierge extra 3,9%, oignon, + olive noire entière dénoyautée saumurée 2,5% (olive, eau, sel, correcteurs d'acidité : acide citrique, acide lactique), + ail, basilic 0,9%, amidon de riz, sel" }, # add_fruit() currently matches "olive noire entière dénoyautée saumurée 2,5% (..)" to 2.5% fruit, even though it has sub-ingredients that are not fruits # TODO: investigate on actual product data to see if trying to fix this would have more true positives than false positives - 93.8, - 89.9 + 94.7, + 90.8 ], # Soy beans [ diff --git a/tests/unit/nutriscore.t b/tests/unit/nutriscore.t index 75a49ec39d08c..0386f686a8c57 100644 --- a/tests/unit/nutriscore.t +++ b/tests/unit/nutriscore.t @@ -880,6 +880,45 @@ my @tests = ( }, } ], + + # orange + [ + "en-orange", + { + lc => "en", + categories => "oranges", + ingredients_text => "orange", + } + ], + + # pickled vegetable with water and dill: water should not be counted in fruits/vegetables + # dill should be counted + [ + "pl-pickled-vegetables", + { + lc => "pl", + categories => "pickled vegetables", + ingredients_text => "52% rzodkiew biała, woda, koper, 0,6% czosnek, sól, chrzan", + nutriments => { + energy_100g => 53, + fat_100g => 0.1, + "saturated-fat_100g" => 0, + sugars_100g => 0, + sodium_100g => 2, + proteins_100g => 0.7, + }, + } + ], + + # dill + [ + "en-dill", + { + lc => "en", + categories => "dill", + ingredients_text => "dill", + } + ], ); my $json = JSON->new->allow_nonref->canonical;