From b5e657c41c2134ef57f9e8c9ab7e5417fb8ee1fc Mon Sep 17 00:00:00 2001
From: Ernesto Rico Schmidt <ernesto@helsinki.at>
Date: Wed, 23 Feb 2022 15:30:15 -0400
Subject: [PATCH] Introduce get_colliding_timeslots in TimeSlotManager to query
 for collsions

---
 program/models.py | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/program/models.py b/program/models.py
index acd065cc..b093228a 100644
--- a/program/models.py
+++ b/program/models.py
@@ -388,13 +388,7 @@ class Schedule(models.Model):
         collisions = []
 
         for ts in timeslots:
-
-            collision = TimeSlot.objects.filter(
-                (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
-                (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
-                (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
-                (Q(start__lte=ts.start) & Q(end__gte=ts.end))
-            )
+            collision = TimeSlot.objects.get_colliding_timeslots(ts)
 
             if collision:
                 collisions.append(collision[0])  # TODO: Do we really always retrieve one?
@@ -428,12 +422,7 @@ class Schedule(models.Model):
             solution_choices = set()
 
             # Get collisions for each timeslot
-            collision_list = list(TimeSlot.objects.filter(
-                (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
-                (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
-                (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
-                (Q(start__lte=ts.start) & Q(end__gte=ts.end))
-            ).order_by('start'))
+            collision_list = list(TimeSlot.objects.get_colliding_timeslots(ts).order_by('start'))
 
             # Add the projected timeslot
             projected_entry = {'hash': ts.hash, 'start': str(ts.start), 'end': str(ts.end)}
@@ -853,6 +842,15 @@ class TimeSlotManager(models.Manager):
         return TimeSlot.objects.filter(Q(start__lte=start, end__gte=start) |
                                        Q(start__gt=start, start__lt=end)).exclude(end=start)
 
+    @staticmethod
+    def get_colliding_timeslots(timeslot):
+        return TimeSlot.objects.filter(
+            (Q(start__lt=timeslot.end) & Q(end__gte=timeslot.end)) |
+            (Q(end__gt=timeslot.start) & Q(end__lte=timeslot.end)) |
+            (Q(start__gte=timeslot.start) & Q(end__lte=timeslot.end)) |
+            (Q(start__lte=timeslot.start) & Q(end__gte=timeslot.end))
+        )
+
 
 class TimeSlot(models.Model):
     schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE, related_name='timeslots')
-- 
GitLab