Skip to content

Commit

Permalink
feat: Limit schedule generator by session purpose (#5055)
Browse files Browse the repository at this point in the history
* feat: Limit schedule generator by session purpose

* feat: Raise exceptions if no sessions/timeslots are found
  • Loading branch information
jennifer-richards authored Jan 31, 2023
1 parent 413fd88 commit 7e2b062
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions ietf/meeting/management/commands/generate_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from ietf.person.models import Person
from ietf.meeting import models
from ietf.meeting.helpers import get_person_by_email
from ietf.name.models import SessionPurposeName


# 40 runs of the optimiser for IETF 106 with cycles=160 resulted in 16
# zero-violation invocations, with a mean number of runs of 91 and
Expand Down Expand Up @@ -72,18 +74,31 @@ def add_arguments(self, parser):
'Base schedule for generated schedule, specified as "[owner/]name"'
' (default is no base schedule; owner not required if name is unique)'
))
parser.add_argument('-p', '--purpose',
dest='purposes',
action='append',
choices=[
spn.slug for spn in SessionPurposeName.objects.all()
if 'regular' in spn.timeslot_types # scheduler only works with "regular" timeslots
],
default=None,
help=(
'Limit scheduling to specified purpose '
'(use option multiple times to specify more than one purpose; default is all purposes)'
))

def handle(self, meeting, name, max_cycles, verbosity, base_id, *args, **kwargs):
ScheduleHandler(self.stdout, meeting, name, max_cycles, verbosity, base_id).run()
def handle(self, meeting, name, max_cycles, verbosity, base_id, purposes, *args, **kwargs):
ScheduleHandler(self.stdout, meeting, name, max_cycles, verbosity, base_id, purposes).run()


class ScheduleHandler(object):
def __init__(self, stdout, meeting_number, name=None, max_cycles=OPTIMISER_MAX_CYCLES,
verbosity=1, base_id=None):
verbosity=1, base_id=None, session_purposes=None):
self.stdout = stdout
self.verbosity = verbosity
self.name = name
self.max_cycles = max_cycles
self.session_purposes = session_purposes
if meeting_number:
try:
self.meeting = models.Meeting.objects.get(type="ietf", number=meeting_number)
Expand Down Expand Up @@ -114,6 +129,10 @@ def __init__(self, stdout, meeting_number, name=None, max_cycles=OPTIMISER_MAX_C
msgs.append('Applying schedule {} as base schedule'.format(ScheduleId.from_schedule(self.base_schedule)))
self.stdout.write('\n{}\n\n'.format('\n'.join(msgs)))
self._load_meeting()
if len(self.schedule.sessions) == 0:
raise CommandError('No sessions found to schedule')
if len(self.schedule.timeslots) == 0:
raise CommandError('No timeslots found for schedule')

def run(self):
"""Schedule all sessions"""
Expand Down Expand Up @@ -194,6 +213,8 @@ def _sessions_to_schedule(self, *args, **kwargs):
Extra arguments are passed to the Session constructor.
"""
sessions_db = self.meeting.session_set.that_can_be_scheduled().filter(type_id='regular')
if self.session_purposes is not None:
sessions_db = sessions_db.filter(purpose__slug__in=self.session_purposes)
if self.base_schedule is None:
fixed_sessions = models.Session.objects.none()
else:
Expand Down

0 comments on commit 7e2b062

Please sign in to comment.