-
-
Notifications
You must be signed in to change notification settings - Fork 407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: New system to show how well products match user preferences #6764
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me there are potential issues with status computation.
html/js/product-search.js
Outdated
else if ((attribute_preference == "mandatory") && (attribute.match <= 50) | ||
&& ((status = "match") || (status = "may-not-match"))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean ===
, don't you ?
Where does the "may-not-match" comes from ?
html/js/product-search.js
Outdated
@@ -16,7 +16,7 @@ | |||
function match_product_to_preferences (product, product_preferences) { | |||
|
|||
var score = 0; | |||
var status = "yes"; | |||
var status = "compatible"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document possible values of status here.
html/js/product-search.js
Outdated
else if (status == "does_not_match") { | ||
score = 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would do this above (as suggested) for this is not logical to have it here…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
html/js/product-search.js
Outdated
// Normalize the score from 0 to 100 | ||
score /= sum_of_factors; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Normalize the score from 0 to 100 | |
score /= sum_of_factors; | |
if (status !== "does_not_match") { | |
// Normalize the score from 0 to 100 | |
score /= sum_of_factors; | |
else { | |
score = 0; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I'm not sure why we don't have "may_not_match"
and "unknown_match"
in the condition.
html/js/product-search.js
Outdated
product_html += '<div class="list_product_banner list_product_banner_' + product.match_status + '">' | ||
+ lang()["products_match_" + product.match_status] + ' ' + Math.round(product.match_score) + '/100</div>' | ||
+ '<div class="list_product_content">'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal: why did you remove the use of javascript template ? it's less readable IMO.
lib/ProductOpener/Attributes.pm
Outdated
@@ -813,7 +813,7 @@ sub compute_attribute_nova($$) { | |||
$match = 100; | |||
} | |||
elsif ($nova_group == 3) { | |||
$match = 50; | |||
$match = 75; | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: This part could be better written as a lookup in a hash with scores.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
html/js/product-search.js
Outdated
|
||
products.sort(function(a, b) { | ||
return (b.match_score - a.match_score) || (a.initial_order - b.initial_order); | ||
return (b.match_score - a.match_score) // Highest score first | ||
|| ((a.match_status == "does_not_match" ? 1 : 0) - (b.match_status == "does_not_match" ? 1 : 0)) // Matching products second |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use ===
for matching in js.
Why "does_not_match" gives me 1 point instead of 0 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also is it normal that we do not consider the other status like may_not_match ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hum I see, it's because you reversed a and b order compared to above expression.
I would better have:
((b.match_status == "does_not_match" ? 0 : 1) - (a.match_status == "does_not_match" ? 0 : 1)) // Matching products second
but it's ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll change, and use === instead of ==
@stephanegigandet we could add a selector on the top to hide some status (eg. unknown etc)… but for a future version ;-) |
Right, in fact it's mostly for debugging purposes, I'm not sure we will show the score at all in the final version, maybe just the status.
Sure, we can put a lighter grey. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good, just a potential bug, that is better to fix ;-)
} | ||
else { | ||
product.match_status = "poor_match"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool refactor 👍
Co-authored-by: Alex Garel <alex@garel.org>
Kudos, SonarCloud Quality Gate passed!
|
This is an implementation of the product scoring system described in https://forum.openfoodfacts.org/t/proposal-for-a-new-personalized-experience-in-the-open-food-facts-app-and-website/71
Scores are now on a 0 to 100 scale
Product match status is now either:
and if the user selected some hard restrictions (e.g. vegan, or allergens) (currently selected by marking the attribute mandatory, but we could make new settings specific for restrictions that would be binary "I'm allergic to gluten"):
Product match status is now indicated at the top of the card, in a similar way to the new Flutter app.
The score is now displayed, but we could hide it. I display it currently for debugging purposes.
I removed the pagination at the top, it's now only on the bottom.
I removed the tabs for each match status, to make the interface cleaner.
Screenshot:
![image](https://user-images.githubusercontent.com/8158668/168083893-a5dec0ac-fd63-4792-8fcd-ca3b34dc48f7.png)
2 minute video demo:
https://www.loom.com/share/33ca5a6179bd49b29ad2404a1b1af2ff