Merge pull request #1356 from jooola/fix/api_cueout

Fix cueout for schedule starts overlapping show ends
This commit is contained in:
Jonas L 2021-09-21 15:29:15 +02:00 committed by GitHub
commit f9f7f83ef7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 10 deletions

View File

@ -24,26 +24,58 @@ class Schedule(models.Model):
def get_cueout(self):
"""
Returns a cueout that is based on the current show. Cueout of a specific
item can potentially overrun the show that it is scheduled in. In that
case, the cueout should be the end of the show. This prevents the next
show having overlapping items playing.
Returns a scheduled item cueout that is based on the current show instance.
Cueout of a specific item can potentially overrun the show that it is
scheduled in. In that case, the cueout should be the end of the show.
This prevents the next show having overlapping items playing.
Cases:
- When the schedule ends before the end of the show instance,
return the stored cueout.
- When the schedule starts before the end of the show instance
and ends after the show instance ends,
return timedelta between schedule starts and show instance ends.
- When the schedule starts after the end of the show instance,
return the stored cue_out even if the schedule WILL NOT BE PLAYED.
"""
if self.instance.ends < self.ends:
if self.starts < self.instance.ends and self.instance.ends < self.ends:
return self.instance.ends - self.starts
return self.cue_out
def get_ends(self):
"""
Returns an item end that is based on the current show. Ends of a
specific item can potentially overrun the show that it is scheduled in.
In that case, the end should be the end of the show. This prevents the
next show having overlapping items playing.
Returns a scheduled item ends that is based on the current show instance.
End of a specific item can potentially overrun the show that it is
scheduled in. In that case, the end should be the end of the show.
This prevents the next show having overlapping items playing.
Cases:
- When the schedule ends before the end of the show instance,
return the scheduled item ends.
- When the schedule starts before the end of the show instance
and ends after the show instance ends,
return the show instance ends.
- When the schedule starts after the end of the show instance,
return the show instance ends.
"""
if self.instance.ends < self.ends:
return self.instance.ends
return self.ends
@property
def is_valid(self):
"""
A schedule item is valid if it starts before the end of the show instance
it is in
"""
return self.starts < self.instance.ends
class Meta:
managed = False
db_table = "cc_schedule"

View File

@ -0,0 +1,56 @@
from datetime import datetime, timedelta
from django.test import SimpleTestCase
from libretimeapi.models import Schedule, ShowInstance
class TestSchedule(SimpleTestCase):
@classmethod
def setUpTestData(cls):
cls.show_instance = ShowInstance(
created=datetime(year=2021, month=10, day=1, hour=12),
starts=datetime(year=2021, month=10, day=2, hour=1),
ends=datetime(year=2021, month=10, day=2, hour=2),
)
cls.length = timedelta(minutes=10)
cls.cue_in = timedelta(seconds=1)
cls.cue_out = cls.length - timedelta(seconds=4)
def create_schedule(self, starts):
return Schedule(
starts=starts,
ends=starts + self.length,
cue_in=self.cue_in,
cue_out=self.cue_out,
instance=self.show_instance,
)
def test_get_cueout(self):
# No overlapping schedule datetimes, normal usecase:
s1_starts = datetime(year=2021, month=10, day=2, hour=1, minute=30)
s1 = self.create_schedule(s1_starts)
self.assertEqual(s1.get_cueout(), self.cue_out)
self.assertEqual(s1.get_ends(), s1_starts + self.length)
# Mixed overlapping schedule datetimes (only ends is overlapping):
s2_starts = datetime(year=2021, month=10, day=2, hour=1, minute=55)
s2 = self.create_schedule(s2_starts)
self.assertEqual(s2.get_cueout(), timedelta(minutes=5))
self.assertEqual(s2.get_ends(), self.show_instance.ends)
# Fully overlapping schedule datetimes (starts and ends are overlapping):
s3_starts = datetime(year=2021, month=10, day=2, hour=2, minute=1)
s3 = self.create_schedule(s3_starts)
self.assertEqual(s3.get_cueout(), self.cue_out)
self.assertEqual(s3.get_ends(), self.show_instance.ends)
def test_is_valid(self):
# Starts before the schedule ends
s1_starts = datetime(year=2021, month=10, day=2, hour=1, minute=30)
s1 = self.create_schedule(s1_starts)
self.assertTrue(s1.is_valid)
# Starts after the schedule ends
s2_starts = datetime(year=2021, month=10, day=2, hour=3)
s2 = self.create_schedule(s2_starts)
self.assertFalse(s2.is_valid)

View File

@ -141,7 +141,7 @@ class PreferenceViewSet(viewsets.ModelViewSet):
class ScheduleViewSet(viewsets.ModelViewSet):
queryset = Schedule.objects.all()
serializer_class = ScheduleSerializer
filter_fields = ("starts", "ends", "playout_status", "broadcasted")
filter_fields = ("starts", "ends", "playout_status", "broadcasted", "is_valid")
model_permission_name = "schedule"

View File

@ -54,6 +54,7 @@ class AirtimeApiClient:
data = self.services.schedule_url(
params={
"ends__range": ("{}Z,{}Z".format(str_current, str_end)),
"is_valid": True,
}
)
result = {"media": {}}