Skip to content

Commit

Permalink
feat: Allow a percent_max to be specified in ingredients Fixes #5369 (#…
Browse files Browse the repository at this point in the history
…7639)

* Allow a percent_max to be specified in ingredients

* Update lib/ProductOpener/Ingredients.pm

Co-authored-by: Stéphane Gigandet <stephane@openfoodfacts.org>

* Additional guard against maximum. Note test doesn't fail without this

* Make else block consistent

* Set MSYS_NO_PATHCONV for Windows and added update_tests_results make task

* Limiting scope so can't contradict stated percentages

* Catch empty ingredients and removed debugging

* Fix perltidty

* Fix for perlcritic

* Cope with multiple constrained ingredients

Co-authored-by: Stéphane Gigandet <stephane@openfoodfacts.org>
  • Loading branch information
john-gom and stephanegigandet authored Nov 9, 2022
1 parent 8ed94b8 commit e01e83f
Show file tree
Hide file tree
Showing 9 changed files with 3,079 additions and 1,436 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ UID ?= $(shell id -u)
export USER_UID:=${UID}

export CPU_COUNT=$(shell nproc || echo 1)

export MSYS_NO_PATHCONV=1

DOCKER_COMPOSE=docker-compose --env-file=${ENV_FILE}
# we run tests in a specific project name to be separated from dev instances
Expand Down Expand Up @@ -224,6 +224,10 @@ test-int: guard-test # usage: make test-one test=test-file.t
stop_tests:
${DOCKER_COMPOSE_TEST} stop

update_tests_results:
@echo "🥫 Updated expected test results with actuals for easy Git diff"
${DOCKER_COMPOSE_TEST} run --rm -w /opt/product-opener/tests backend bash update_tests_results.sh

# check perl compiles, (pattern rule) / but only for newer files
%.pm %.pl: _FORCE
if [ -f $@ ]; then perl -c -CS -Ilib $@; else true; fi
Expand Down
64 changes: 64 additions & 0 deletions lib/ProductOpener/Ingredients.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,10 @@ Otherwise use 0 for percent_min and total_max for percent_max.
=cut

sub init_percent_values ($total_min, $total_max, $ingredients_ref) {
# Set maximum percentages if defined in the taxonomy (only do this for top-level ingredients)
if ($total_max == 100) {
set_percent_max_from_taxonomy($ingredients_ref);
}

# Determine if percent listed are absolute (default) or relative to a parent ingredient

Expand Down Expand Up @@ -2542,6 +2546,66 @@ sub init_percent_values ($total_min, $total_max, $ingredients_ref) {
return;
}

=head2 set_percent_max_from_taxonomy ( ingredients_ref )
Set the percentage maximum for ingredients like flavouring where this is defined
on the Ingredients taxonomy. The percent_max will not be applied in the following cases:
- if applying the percent_max would mean that it is not possible for the ingredient
total to add up to 100%
- If a later ingredient has a higher percentage than the percent_max of the restricted ingredient
=cut

sub set_percent_max_from_taxonomy ($ingredients_ref) {
# Exit if the first ingredient is constrained
if (!@{$ingredients_ref}
|| defined get_inherited_property("ingredients", $ingredients_ref->[0]{id}, "percent_max:en"))
{
return;
}

# Loop backwards through ingredients, checking that we don't set a percent_max that
# would be lower than the defined percentage of any ingredient that comes afterwards
my $highest_later_percent = 0;
for (my $index = scalar @{$ingredients_ref} - 1; $index > 0; $index--) {
my $ingredient = $ingredients_ref->[$index];
my $current_percent = $ingredient->{percent};
if (defined $current_percent) {
if ($current_percent > $highest_later_percent) {
$highest_later_percent = $current_percent;
}
}
else {
# See if taxonomy defines a maximum percent
my $percent_max = get_inherited_property("ingredients", $ingredient->{id}, "percent_max:en");
if (defined $percent_max and $percent_max >= $highest_later_percent) {
# Maximum percantage for ingredients like flavourings
$ingredient->{percent_max} = $percent_max;
}
}
}

# Loop forwards through the ingredients to make sure that the maximum
# does not limit preceding ingredients where percent is specified
my $remaining_percent = 100;
for my $ingredient (@{$ingredients_ref}) {
my $defined_percent = $ingredient->{percent};
if (!defined $defined_percent) {
my $percent_max = $ingredient->{percent_max};
if (defined $percent_max && $percent_max < $remaining_percent) {
delete $ingredient->{percent_max};
}
last;
}
else {
$remaining_percent = $remaining_percent - $defined_percent;
}
}

return;
}

sub set_percent_max_values ($total_min, $total_max, $ingredients_ref) {

my $changed = 0;
Expand Down
4,013 changes: 2,670 additions & 1,343 deletions taxonomies/ingredients.all.txt

Large diffs are not rendered by default.

Binary file modified taxonomies/ingredients.result.sto
Binary file not shown.
Loading

0 comments on commit e01e83f

Please sign in to comment.