prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [feat] Make `exclude_compared` configurable in user settings
  
  
  </issue>
  <code>
  [start of backend/core/serializers/user_settings.py]
  1 from django.utils.translation import gettext_lazy as _
  2 from rest_framework import serializers
  3 from rest_framework.serializers import ValidationError
  4 
  5 from tournesol.models.poll import Poll
  6 from tournesol.utils.video_language import ACCEPTED_LANGUAGE_CODES
  7 
  8 
  9 class GeneralUserSettingsSerializer(serializers.Serializer):
  10     """
  11     The general user settings that are not related to Tournesol polls.
  12     """
  13 
  14     # The first element of the tuple should be an ISO 639-1 code.
  15     NOTIFICATIONS_LANG = [
  16         ("en", "en"),
  17         ("fr", "fr"),
  18     ]
  19 
  20     notifications__lang = serializers.ChoiceField(
  21         choices=NOTIFICATIONS_LANG, required=False
  22     )
  23     notifications_email__research = serializers.BooleanField(required=False)
  24     notifications_email__new_features = serializers.BooleanField(required=False)
  25 
  26 
  27 class GenericPollUserSettingsSerializer(serializers.Serializer):
  28     """
  29     The settings common to each poll.
  30     """
  31 
  32     COMPONENT_DISPLAY_STATE = [
  33         ("ALWAYS", "always"),
  34         ("EMBEDDED_ONLY", "embedded_only"),
  35         ("WEBSITE_ONLY", "website_only"),
  36         ("NEVER", "never"),
  37     ]
  38 
  39     comparison__criteria_order = serializers.ListField(
  40         child=serializers.CharField(), required=False
  41     )
  42 
  43     comparison__fill_entity_selector = serializers.BooleanField(required=False)
  44 
  45     comparison_ui__weekly_collective_goal_display = serializers.ChoiceField(
  46         choices=COMPONENT_DISPLAY_STATE, allow_blank=True, required=False
  47     )
  48 
  49     rate_later__auto_remove = serializers.IntegerField(required=False)
  50 
  51     def validate_comparison__criteria_order(self, criteria):
  52         poll_name = self.context.get("poll_name", self._context["poll_name"])
  53         poll = Poll.objects.get(name=poll_name)
  54 
  55         if poll.main_criteria in criteria:
  56             raise ValidationError(_("The main criterion cannot be in the list."))
  57 
  58         if len(criteria) != len(set(criteria)):
  59             raise ValidationError(_("The list cannot contain duplicates."))
  60 
  61         for criterion in criteria:
  62             if criterion not in poll.criterias_list:
  63                 raise ValidationError(
  64                     _("Unknown criterion: %(criterion)s.") % {"criterion": criterion}
  65                 )
  66 
  67         return criteria
  68 
  69     def validate_rate_later__auto_remove(self, value):
  70         if value < 1:
  71             raise ValidationError(_("This parameter cannot be lower than 1."))
  72         return value
  73 
  74 
  75 class VideosPollUserSettingsSerializer(GenericPollUserSettingsSerializer):
  76     """
  77     The settings specific to the `videos` poll.
  78 
  79     Also inherit the settings common to each poll.
  80     """
  81 
  82     DEFAULT_DATE_CHOICES = [
  83         ("TODAY", "today"),
  84         ("WEEK", "week"),
  85         ("MONTH", "month"),
  86         ("YEAR", "year"),
  87         ("ALL_TIME", "all_time"),
  88     ]
  89 
  90     recommendations__default_date = serializers.ChoiceField(
  91         choices=DEFAULT_DATE_CHOICES, allow_blank=True, required=False
  92     )
  93     recommendations__default_languages = serializers.ListField(
  94         child=serializers.CharField(), allow_empty=True, required=False
  95     )
  96     recommendations__default_unsafe = serializers.BooleanField(required=False)
  97 
  98     def validate_recommendations__default_languages(self, default_languages):
  99         for lang in default_languages:
  100             if lang not in ACCEPTED_LANGUAGE_CODES:
  101                 raise ValidationError(_("Unknown language code: %(lang)s.") % {"lang": lang})
  102 
  103         return default_languages
  104 
  105 
  106 class TournesolUserSettingsSerializer(serializers.Serializer):
  107     """
  108     A representation of all user settings of the Tournesol project.
  109 
  110     This representation includes poll-agnostic settings in addition to the
  111     specific settings of each poll.
  112     """
  113 
  114     general = GeneralUserSettingsSerializer(required=False)
  115     videos = VideosPollUserSettingsSerializer(required=False, context={"poll_name": "videos"})
  116 
  117     def create(self, validated_data):
  118         return validated_data
  119 
  120     def update(self, instance, validated_data):
  121         for scope, settings in self.validated_data.items():
  122             if scope not in instance:
  123                 instance[scope] = {}
  124             instance[scope].update(settings)
  125         return instance
  126
  [end of backend/core/serializers/user_settings.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/backend/core/serializers/user_settings.py b/backend/core/serializers/user_settings.py
  --- a/backend/core/serializers/user_settings.py
  +++ b/backend/core/serializers/user_settings.py
  @@ -94,6 +94,7 @@
           child=serializers.CharField(), allow_empty=True, required=False
       )
       recommendations__default_unsafe = serializers.BooleanField(required=False)
  +    recommendations__default_exclude_compared_entities = serializers.BooleanField(required=False)
   
       def validate_recommendations__default_languages(self, default_languages):
           for lang in default_languages:
  
verification_info: {"golden_diff": "diff --git a/backend/core/serializers/user_settings.py b/backend/core/serializers/user_settings.py\n--- a/backend/core/serializers/user_settings.py\n+++ b/backend/core/serializers/user_settings.py\n@@ -94,6 +94,7 @@\n         child=serializers.CharField(), allow_empty=True, required=False\n     )\n     recommendations__default_unsafe = serializers.BooleanField(required=False)\n+    recommendations__default_exclude_compared_entities = serializers.BooleanField(required=False)\n \n     def validate_recommendations__default_languages(self, default_languages):\n         for lang in default_languages:\n", "issue": "[feat] Make `exclude_compared` configurable in user settings\n\n", "before_files": [{"content": "from django.utils.translation import gettext_lazy as _\nfrom rest_framework import serializers\nfrom rest_framework.serializers import ValidationError\n\nfrom tournesol.models.poll import Poll\nfrom tournesol.utils.video_language import ACCEPTED_LANGUAGE_CODES\n\n\nclass GeneralUserSettingsSerializer(serializers.Serializer):\n    \"\"\"\n    The general user settings that are not related to Tournesol polls.\n    \"\"\"\n\n    # The first element of the tuple should be an ISO 639-1 code.\n    NOTIFICATIONS_LANG = [\n        (\"en\", \"en\"),\n        (\"fr\", \"fr\"),\n    ]\n\n    notifications__lang = serializers.ChoiceField(\n        choices=NOTIFICATIONS_LANG, required=False\n    )\n    notifications_email__research = serializers.BooleanField(required=False)\n    notifications_email__new_features = serializers.BooleanField(required=False)\n\n\nclass GenericPollUserSettingsSerializer(serializers.Serializer):\n    \"\"\"\n    The settings common to each poll.\n    \"\"\"\n\n    COMPONENT_DISPLAY_STATE = [\n        (\"ALWAYS\", \"always\"),\n        (\"EMBEDDED_ONLY\", \"embedded_only\"),\n        (\"WEBSITE_ONLY\", \"website_only\"),\n        (\"NEVER\", \"never\"),\n    ]\n\n    comparison__criteria_order = serializers.ListField(\n        child=serializers.CharField(), required=False\n    )\n\n    comparison__fill_entity_selector = serializers.BooleanField(required=False)\n\n    comparison_ui__weekly_collective_goal_display = serializers.ChoiceField(\n        choices=COMPONENT_DISPLAY_STATE, allow_blank=True, required=False\n    )\n\n    rate_later__auto_remove = serializers.IntegerField(required=False)\n\n    def validate_comparison__criteria_order(self, criteria):\n        poll_name = self.context.get(\"poll_name\", self._context[\"poll_name\"])\n        poll = Poll.objects.get(name=poll_name)\n\n        if poll.main_criteria in criteria:\n            raise ValidationError(_(\"The main criterion cannot be in the list.\"))\n\n        if len(criteria) != len(set(criteria)):\n            raise ValidationError(_(\"The list cannot contain duplicates.\"))\n\n        for criterion in criteria:\n            if criterion not in poll.criterias_list:\n                raise ValidationError(\n                    _(\"Unknown criterion: %(criterion)s.\") % {\"criterion\": criterion}\n                )\n\n        return criteria\n\n    def validate_rate_later__auto_remove(self, value):\n        if value < 1:\n            raise ValidationError(_(\"This parameter cannot be lower than 1.\"))\n        return value\n\n\nclass VideosPollUserSettingsSerializer(GenericPollUserSettingsSerializer):\n    \"\"\"\n    The settings specific to the `videos` poll.\n\n    Also inherit the settings common to each poll.\n    \"\"\"\n\n    DEFAULT_DATE_CHOICES = [\n        (\"TODAY\", \"today\"),\n        (\"WEEK\", \"week\"),\n        (\"MONTH\", \"month\"),\n        (\"YEAR\", \"year\"),\n        (\"ALL_TIME\", \"all_time\"),\n    ]\n\n    recommendations__default_date = serializers.ChoiceField(\n        choices=DEFAULT_DATE_CHOICES, allow_blank=True, required=False\n    )\n    recommendations__default_languages = serializers.ListField(\n        child=serializers.CharField(), allow_empty=True, required=False\n    )\n    recommendations__default_unsafe = serializers.BooleanField(required=False)\n\n    def validate_recommendations__default_languages(self, default_languages):\n        for lang in default_languages:\n            if lang not in ACCEPTED_LANGUAGE_CODES:\n                raise ValidationError(_(\"Unknown language code: %(lang)s.\") % {\"lang\": lang})\n\n        return default_languages\n\n\nclass TournesolUserSettingsSerializer(serializers.Serializer):\n    \"\"\"\n    A representation of all user settings of the Tournesol project.\n\n    This representation includes poll-agnostic settings in addition to the\n    specific settings of each poll.\n    \"\"\"\n\n    general = GeneralUserSettingsSerializer(required=False)\n    videos = VideosPollUserSettingsSerializer(required=False, context={\"poll_name\": \"videos\"})\n\n    def create(self, validated_data):\n        return validated_data\n\n    def update(self, instance, validated_data):\n        for scope, settings in self.validated_data.items():\n            if scope not in instance:\n                instance[scope] = {}\n            instance[scope].update(settings)\n        return instance\n", "path": "backend/core/serializers/user_settings.py"}]}