prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Make minors identifiable on event detail page
  As an Einsatzleiter, I want to quickly grasp which participants are younger than 18 years. For that purpose, I want to have the participation boxes on the event detail page/shift box to display a small warning/indication, e.g. a red corner or similar.
  
  </issue>
  <code>
  [start of ephios/core/signup/participants.py]
  1 import dataclasses
  2 import functools
  3 from datetime import date
  4 from typing import Optional
  5 
  6 from django.contrib.auth import get_user_model
  7 from django.db.models import QuerySet
  8 from django.urls import reverse
  9 from django.utils.safestring import mark_safe
  10 from django.utils.translation import gettext_lazy as _
  11 
  12 from ephios.core.models import AbstractParticipation, LocalParticipation, Qualification
  13 from ephios.core.models.events import PlaceholderParticipation
  14 
  15 
  16 @dataclasses.dataclass(frozen=True)
  17 class AbstractParticipant:
  18     first_name: str
  19     last_name: str
  20     qualifications: QuerySet = dataclasses.field(hash=False)
  21     date_of_birth: Optional[date]
  22     email: Optional[str]  # if set to None, no notifications are sent
  23 
  24     def get_age(self, today: date = None):
  25         if self.date_of_birth is None:
  26             return None
  27         today, born = today or date.today(), self.date_of_birth
  28         return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
  29 
  30     def __str__(self):
  31         return f"{self.first_name} {self.last_name}"
  32 
  33     def new_participation(self, shift):
  34         raise NotImplementedError
  35 
  36     def participation_for(self, shift):
  37         """Return the participation object for a shift. Return None if it does not exist."""
  38         raise NotImplementedError
  39 
  40     def all_participations(self):
  41         """Return all participations for this participant"""
  42         raise NotImplementedError
  43 
  44     @functools.lru_cache(maxsize=64)
  45     def collect_all_qualifications(self) -> set:
  46         return Qualification.collect_all_included_qualifications(self.qualifications)
  47 
  48     def has_qualifications(self, qualifications):
  49         return set(qualifications) <= self.collect_all_qualifications()
  50 
  51     def reverse_signup_action(self, shift):
  52         raise NotImplementedError
  53 
  54     def reverse_event_detail(self, event):
  55         raise NotImplementedError
  56 
  57     @property
  58     def icon(self):
  59         return mark_safe('<span class="fa fa-user"></span>')
  60 
  61 
  62 @dataclasses.dataclass(frozen=True)
  63 class LocalUserParticipant(AbstractParticipant):
  64     user: get_user_model()
  65 
  66     def new_participation(self, shift):
  67         return LocalParticipation(shift=shift, user=self.user)
  68 
  69     def participation_for(self, shift):
  70         try:
  71             return LocalParticipation.objects.get(shift=shift, user=self.user)
  72         except LocalParticipation.DoesNotExist:
  73             return None
  74 
  75     def all_participations(self):
  76         return LocalParticipation.objects.filter(user=self.user)
  77 
  78     def reverse_signup_action(self, shift):
  79         return reverse("core:signup_action", kwargs=dict(pk=shift.pk))
  80 
  81     def reverse_event_detail(self, event):
  82         return event.get_absolute_url()
  83 
  84 
  85 @dataclasses.dataclass(frozen=True)
  86 class PlaceholderParticipant(AbstractParticipant):
  87     def new_participation(self, shift):
  88         return PlaceholderParticipation(
  89             shift=shift, first_name=self.first_name, last_name=self.last_name
  90         )
  91 
  92     def participation_for(self, shift):
  93         try:
  94             return PlaceholderParticipation.objects.get(
  95                 shift=shift, first_name=self.first_name, last_name=self.last_name
  96             )
  97         except PlaceholderParticipation.DoesNotExist:
  98             return None
  99 
  100     def all_participations(self):
  101         return AbstractParticipation.objects.none()
  102 
  103     def reverse_signup_action(self, shift):
  104         raise NotImplementedError
  105 
  106     def reverse_event_detail(self, event):
  107         raise NotImplementedError
  108 
  109     @property
  110     def icon(self):
  111         return mark_safe(
  112             f'<span class="fa fa-user-tag" data-toggle="tooltip" data-placement="left" title="{_("Placeholder")}"></span>'
  113         )
  114
  [end of ephios/core/signup/participants.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/ephios/core/signup/participants.py b/ephios/core/signup/participants.py
  --- a/ephios/core/signup/participants.py
  +++ b/ephios/core/signup/participants.py
  @@ -27,6 +27,12 @@
           today, born = today or date.today(), self.date_of_birth
           return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
   
  +    @property
  +    def is_minor(self):
  +        if age := self.get_age():
  +            return age < 18
  +        return False
  +
       def __str__(self):
           return f"{self.first_name} {self.last_name}"
  
verification_info: {"golden_diff": "diff --git a/ephios/core/signup/participants.py b/ephios/core/signup/participants.py\n--- a/ephios/core/signup/participants.py\n+++ b/ephios/core/signup/participants.py\n@@ -27,6 +27,12 @@\n         today, born = today or date.today(), self.date_of_birth\n         return today.year - born.year - ((today.month, today.day) < (born.month, born.day))\n \n+    @property\n+    def is_minor(self):\n+        if age := self.get_age():\n+            return age < 18\n+        return False\n+\n     def __str__(self):\n         return f\"{self.first_name} {self.last_name}\"\n", "issue": "Make minors identifiable on event detail page\nAs an Einsatzleiter, I want to quickly grasp which participants are younger than 18 years. For that purpose, I want to have the participation boxes on the event detail page/shift box to display a small warning/indication, e.g. a red corner or similar.\n", "before_files": [{"content": "import dataclasses\nimport functools\nfrom datetime import date\nfrom typing import Optional\n\nfrom django.contrib.auth import get_user_model\nfrom django.db.models import QuerySet\nfrom django.urls import reverse\nfrom django.utils.safestring import mark_safe\nfrom django.utils.translation import gettext_lazy as _\n\nfrom ephios.core.models import AbstractParticipation, LocalParticipation, Qualification\nfrom ephios.core.models.events import PlaceholderParticipation\n\n\n@dataclasses.dataclass(frozen=True)\nclass AbstractParticipant:\n    first_name: str\n    last_name: str\n    qualifications: QuerySet = dataclasses.field(hash=False)\n    date_of_birth: Optional[date]\n    email: Optional[str]  # if set to None, no notifications are sent\n\n    def get_age(self, today: date = None):\n        if self.date_of_birth is None:\n            return None\n        today, born = today or date.today(), self.date_of_birth\n        return today.year - born.year - ((today.month, today.day) < (born.month, born.day))\n\n    def __str__(self):\n        return f\"{self.first_name} {self.last_name}\"\n\n    def new_participation(self, shift):\n        raise NotImplementedError\n\n    def participation_for(self, shift):\n        \"\"\"Return the participation object for a shift. Return None if it does not exist.\"\"\"\n        raise NotImplementedError\n\n    def all_participations(self):\n        \"\"\"Return all participations for this participant\"\"\"\n        raise NotImplementedError\n\n    @functools.lru_cache(maxsize=64)\n    def collect_all_qualifications(self) -> set:\n        return Qualification.collect_all_included_qualifications(self.qualifications)\n\n    def has_qualifications(self, qualifications):\n        return set(qualifications) <= self.collect_all_qualifications()\n\n    def reverse_signup_action(self, shift):\n        raise NotImplementedError\n\n    def reverse_event_detail(self, event):\n        raise NotImplementedError\n\n    @property\n    def icon(self):\n        return mark_safe('<span class=\"fa fa-user\"></span>')\n\n\n@dataclasses.dataclass(frozen=True)\nclass LocalUserParticipant(AbstractParticipant):\n    user: get_user_model()\n\n    def new_participation(self, shift):\n        return LocalParticipation(shift=shift, user=self.user)\n\n    def participation_for(self, shift):\n        try:\n            return LocalParticipation.objects.get(shift=shift, user=self.user)\n        except LocalParticipation.DoesNotExist:\n            return None\n\n    def all_participations(self):\n        return LocalParticipation.objects.filter(user=self.user)\n\n    def reverse_signup_action(self, shift):\n        return reverse(\"core:signup_action\", kwargs=dict(pk=shift.pk))\n\n    def reverse_event_detail(self, event):\n        return event.get_absolute_url()\n\n\n@dataclasses.dataclass(frozen=True)\nclass PlaceholderParticipant(AbstractParticipant):\n    def new_participation(self, shift):\n        return PlaceholderParticipation(\n            shift=shift, first_name=self.first_name, last_name=self.last_name\n        )\n\n    def participation_for(self, shift):\n        try:\n            return PlaceholderParticipation.objects.get(\n                shift=shift, first_name=self.first_name, last_name=self.last_name\n            )\n        except PlaceholderParticipation.DoesNotExist:\n            return None\n\n    def all_participations(self):\n        return AbstractParticipation.objects.none()\n\n    def reverse_signup_action(self, shift):\n        raise NotImplementedError\n\n    def reverse_event_detail(self, event):\n        raise NotImplementedError\n\n    @property\n    def icon(self):\n        return mark_safe(\n            f'<span class=\"fa fa-user-tag\" data-toggle=\"tooltip\" data-placement=\"left\" title=\"{_(\"Placeholder\")}\"></span>'\n        )\n", "path": "ephios/core/signup/participants.py"}]}