Skip to content

Commit

Permalink
fix: milk, dairy drinks and plant-based beverages Nutri-Score 2023 (#…
Browse files Browse the repository at this point in the history
…9141)

In the new Nutri-Score formula, milk, dairy drinks and dairy drinks substitutes are considered beverages.
  • Loading branch information
stephanegigandet authored Oct 11, 2023
1 parent 5999a56 commit 955506e
Show file tree
Hide file tree
Showing 9 changed files with 588 additions and 52 deletions.
30 changes: 27 additions & 3 deletions lib/ProductOpener/Config_off.pm
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ XML
;

# Nutriscore: categories that are never considered beverages for Nutri-Score computation
$options{categories_not_considered_as_beverages_for_nutriscore} = [
$options{categories_not_considered_as_beverages_for_nutriscore_2021} = [
qw(
en:plant-milks
en:milks
Expand All @@ -498,16 +498,40 @@ $options{categories_not_considered_as_beverages_for_nutriscore} = [
)
];

# categories that are considered as beverages
$options{categories_not_considered_as_beverages_for_nutriscore_2023} = [
qw(
en:meal-replacement
en:soups
)
];

# categories that are considered as beverages for Nutri-Score 2021
# unless they have 80% milk (which we will determine through ingredients analysis)
$options{categories_considered_as_beverages_for_nutriscore} = [
$options{categories_considered_as_beverages_for_nutriscore_2021} = [
qw(
en:tea-based-beverages
en:iced-teas
en:herbal-tea-beverages
en:coffee-beverages
en:coffee-drinks
en:coffees
en:herbal-teas
en:teas
)
];

# categories that are considered as beverages for Nutri-Score 2023
$options{categories_considered_as_beverages_for_nutriscore_2023} = [
qw(
en:milks
en:dairy-drinks-substitutes
en:dairy-drinks
en:plant-based-beverages
en:tea-based-beverages
en:iced-teas
en:herbal-tea-beverages
en:coffee-beverages
en:coffee-drinks
en:coffees
en:herbal-teas
en:teas
Expand Down
62 changes: 53 additions & 9 deletions lib/ProductOpener/Food.pm
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ BEGIN {
&fix_salt_equivalent
&is_beverage_for_nutrition_score
&is_beverage_for_nutrition_score_2021
&is_beverage_for_nutrition_score_2023
&is_water_for_nutrition_score
&is_cheese_for_nutrition_score
&is_fat_for_nutrition_score
Expand Down Expand Up @@ -800,26 +801,26 @@ sub canonicalize_nutriment ($target_lc, $nutrient) {
return $nid;
}

=head2 is_beverage_for_nutrition_score( $product_ref )
=head2 is_beverage_for_nutrition_score_2021 ( $product_ref )
Determines if a product should be considered as a beverage for Nutri-Score computations,
based on the product categories.
Dairy drinks are not considered as beverages if they have at least 80% of milk.
2021 Nutri-Score: Dairy drinks are not considered as beverages if they have at least 80% of milk.
=cut

sub is_beverage_for_nutrition_score ($product_ref) {
sub is_beverage_for_nutrition_score_2021 ($product_ref) {

my $is_beverage = 0;

if (has_tag($product_ref, "categories", "en:beverages")) {

$is_beverage = 1;

if (defined $options{categories_not_considered_as_beverages_for_nutriscore}) {
if (defined $options{categories_not_considered_as_beverages_for_nutriscore_2021}) {

foreach my $category_id (@{$options{categories_not_considered_as_beverages_for_nutriscore}}) {
foreach my $category_id (@{$options{categories_not_considered_as_beverages_for_nutriscore_2021}}) {

if (has_tag($product_ref, "categories", $category_id)) {
$is_beverage = 0;
Expand All @@ -829,8 +830,8 @@ sub is_beverage_for_nutrition_score ($product_ref) {
}

# exceptions
if (defined $options{categories_considered_as_beverages_for_nutriscore}) {
foreach my $category_id (@{$options{categories_considered_as_beverages_for_nutriscore}}) {
if (defined $options{categories_considered_as_beverages_for_nutriscore_2021}) {
foreach my $category_id (@{$options{categories_considered_as_beverages_for_nutriscore_2021}}) {

if (has_tag($product_ref, "categories", $category_id)) {
$is_beverage = 1;
Expand All @@ -851,6 +852,49 @@ sub is_beverage_for_nutrition_score ($product_ref) {
return $is_beverage;
}

=head2 is_beverage_for_nutrition_score_2023 ( $product_ref )
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.
=cut

sub is_beverage_for_nutrition_score_2023 ($product_ref) {

my $is_beverage = 0;

if (has_tag($product_ref, "categories", "en:beverages")) {

$is_beverage = 1;

if (defined $options{categories_not_considered_as_beverages_for_nutriscore_2023}) {

foreach my $category_id (@{$options{categories_not_considered_as_beverages_for_nutriscore_2023}}) {

if (has_tag($product_ref, "categories", $category_id)) {
$is_beverage = 0;
last;
}
}
}
}

# exceptions
if (defined $options{categories_considered_as_beverages_for_nutriscore_2023}) {
foreach my $category_id (@{$options{categories_considered_as_beverages_for_nutriscore_2023}}) {

if (has_tag($product_ref, "categories", $category_id)) {
$is_beverage = 1;
last;
}
}
}

return $is_beverage;
}

=head2 is_water_for_nutrition_score( $product_ref )
Determines if a product should be considered as water for Nutri-Score computations,
Expand Down Expand Up @@ -1417,7 +1461,7 @@ sub compute_nutriscore_data ($product_ref, $prepared, $nutriments_field, $versio
my $fruits_vegetables_legumes = compute_nutriscore_2023_fruits_vegetables_legumes($product_ref, $prepared);

my $is_fat_oil_nuts_seeds = is_fat_oil_nuts_seeds_for_nutrition_score($product_ref);
my $is_beverage = $product_ref->{nutrition_score_beverage};
my $is_beverage = is_beverage_for_nutrition_score_2023($product_ref);

$nutriscore_data_ref = {
is_beverage => $is_beverage,
Expand Down
2 changes: 1 addition & 1 deletion lib/ProductOpener/FoodGroups.pm
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ All levels food groups are stored in $product_ref->{food_groups_tags}

sub compute_food_groups ($product_ref) {

$product_ref->{nutrition_score_beverage} = is_beverage_for_nutrition_score($product_ref);
$product_ref->{nutrition_score_beverage} = is_beverage_for_nutrition_score_2021($product_ref);

# Temporarily change categories (backup old one in original_categories_tags)
temporarily_change_categories_for_food_groups_computation($product_ref);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@
"en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients",
"en:nutrition-all-nutriscore-values-known",
"en:nutrition-fruits-vegetables-legumes-estimate-from-ingredients",
"en:nutriscore-2021-same-as-2023",
"en:nutriscore-2021-d-2023-d"
"en:nutriscore-2021-different-from-2023",
"en:nutriscore-2021-better-than-2023",
"en:nutriscore-2021-d-2023-e"
],
"nucleotides_tags" : [],
"nutriments" : {
Expand Down Expand Up @@ -168,15 +169,15 @@
"2023" : {
"category_available" : 1,
"data" : {
"count_proteins" : 0,
"count_proteins_reason" : "negative_points_more_than_11",
"count_proteins" : 1,
"count_proteins_reason" : "beverage",
"energy" : 3378,
"energy_points" : 10,
"fiber" : 2,
"fiber_points" : 0,
"fruits_vegetables_legumes" : 0,
"fruits_vegetables_legumes_points" : 0,
"is_beverage" : 0,
"is_beverage" : 1,
"is_cheese" : 0,
"is_fat_oil_nuts_seeds" : 0,
"is_red_meat_product" : 0,
Expand All @@ -188,33 +189,35 @@
"salt",
"non_nutritive_sweeteners"
],
"negative_points" : 16,
"negative_points" : 22,
"non_nutritive_sweeteners_points" : 0,
"positive_nutrients" : [
"fruits_vegetables_legumes",
"fiber"
"fiber",
"proteins"
],
"positive_points" : 0,
"positive_points" : 7,
"proteins" : 5,
"proteins_points" : 2,
"proteins_points" : 7,
"salt" : 0,
"salt_points" : 0,
"saturated_fat" : 5,
"saturated_fat_points" : 4,
"sugars" : 10,
"sugars_points" : 2
"sugars_points" : 8
},
"grade" : "d",
"grade" : "e",
"nutrients_available" : 1,
"nutriscore_applicable" : 1,
"nutriscore_computed" : 1,
"score" : 16
"score" : 15
}
},
"nutriscore_2021_tags" : [
"d"
],
"nutriscore_2023_tags" : [
"d"
"e"
],
"nutriscore_data" : {
"energy" : 3378,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@
"en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients",
"en:nutrition-all-nutriscore-values-known",
"en:nutrition-fruits-vegetables-legumes-estimate-from-ingredients",
"en:nutriscore-2021-same-as-2023",
"en:nutriscore-2021-d-2023-d"
"en:nutriscore-2021-different-from-2023",
"en:nutriscore-2021-better-than-2023",
"en:nutriscore-2021-d-2023-e"
],
"nucleotides_tags" : [],
"nutriments" : {
Expand Down Expand Up @@ -176,15 +177,15 @@
"2023" : {
"category_available" : 1,
"data" : {
"count_proteins" : 0,
"count_proteins_reason" : "negative_points_more_than_11",
"count_proteins" : 1,
"count_proteins_reason" : "beverage",
"energy" : 3378,
"energy_points" : 10,
"fiber" : 2,
"fiber_points" : 0,
"fruits_vegetables_legumes" : 0,
"fruits_vegetables_legumes_points" : 0,
"is_beverage" : 0,
"is_beverage" : 1,
"is_cheese" : 0,
"is_fat_oil_nuts_seeds" : 0,
"is_red_meat_product" : 0,
Expand All @@ -196,33 +197,35 @@
"salt",
"non_nutritive_sweeteners"
],
"negative_points" : 16,
"negative_points" : 22,
"non_nutritive_sweeteners_points" : 0,
"positive_nutrients" : [
"fruits_vegetables_legumes",
"fiber"
"fiber",
"proteins"
],
"positive_points" : 0,
"positive_points" : 7,
"proteins" : 5,
"proteins_points" : 2,
"proteins_points" : 7,
"salt" : 0,
"salt_points" : 0,
"saturated_fat" : 5,
"saturated_fat_points" : 4,
"sugars" : 10,
"sugars_points" : 2
"sugars_points" : 8
},
"grade" : "d",
"grade" : "e",
"nutrients_available" : 1,
"nutriscore_applicable" : 1,
"nutriscore_computed" : 1,
"score" : 16
"score" : 15
}
},
"nutriscore_2021_tags" : [
"d"
],
"nutriscore_2023_tags" : [
"d"
"e"
],
"nutriscore_data" : {
"energy" : 3378,
Expand Down
Loading

0 comments on commit 955506e

Please sign in to comment.