-
Jonathan Weth authoredJonathan Weth authored
build.py 6.39 KiB
from collections import OrderedDict
from datetime import date
from typing import Union, List
from calendarweek import CalendarWeek
from django.apps import apps
from aleksis.core.models import Person
LessonPeriod = apps.get_model("chronos", "LessonPeriod")
TimePeriod = apps.get_model("chronos", "TimePeriod")
Break = apps.get_model("chronos", "Break")
Supervision = apps.get_model("chronos", "Supervision")
LessonSubstitution = apps.get_model("chronos", "LessonSubstitution")
SupervisionSubstitution = apps.get_model("chronos", "SupervisionSubstitution")
def build_timetable(
type_: str, obj: Union[int, Person], date_ref: Union[CalendarWeek, date]
):
needed_breaks = []
if not isinstance(obj, int):
pk = obj.pk
else:
pk = obj
is_person = False
if type_ == "person":
is_person = True
type_ = obj.timetable_type
# Get matching lesson periods
if is_person:
lesson_periods = LessonPeriod.objects.daily_lessons_for_person(obj, date_ref)
else:
lesson_periods = LessonPeriod.objects.in_week(date_ref).filter_from_type(
type_, obj
)
# Sort lesson periods in a dict
lesson_periods_per_period = {}
for lesson_period in lesson_periods:
period = lesson_period.period.period
weekday = lesson_period.period.weekday
if period not in lesson_periods_per_period:
lesson_periods_per_period[period] = [] if is_person else {}
if not is_person and weekday not in lesson_periods_per_period[period]:
lesson_periods_per_period[period][weekday] = []
if is_person:
lesson_periods_per_period[period].append(lesson_period)
else:
lesson_periods_per_period[period][weekday].append(lesson_period)
if type_ == "teacher":
# Get matching supervisions
if is_person:
week = CalendarWeek.from_date(date_ref)
else:
week = date_ref
supervisions = Supervision.objects.all().annotate_week(week).filter_by_teacher(obj)
if is_person:
supervisions.filter_by_weekday(date_ref.weekday())
supervisions_per_period_after = {}
for supervision in supervisions:
weekday = supervision.break_item.weekday
period_after_break = supervision.break_item.before_period_number
print(supervision, weekday, period_after_break)
if period_after_break not in needed_breaks:
needed_breaks.append(period_after_break)
if (
not is_person
and period_after_break not in supervisions_per_period_after
):
supervisions_per_period_after[period_after_break] = {}
if is_person:
supervisions_per_period_after[period_after_break] = supervision
else:
supervisions_per_period_after[period_after_break][weekday] = supervision
# Get ordered breaks
breaks = OrderedDict(sorted(Break.get_breaks_dict().items()))
rows = []
for period, break_ in breaks.items(): # period is period after break
# Break
if type_ == "teacher" and period in needed_breaks:
row = {
"type": "break",
"after_period": break_.after_period_number,
"before_period": break_.before_period_number,
"time_start": break_.time_start,
"time_end": break_.time_end,
}
if not is_person:
cols = []
for weekday in range(
TimePeriod.weekday_min, TimePeriod.weekday_max + 1
):
col = None
if period in supervisions_per_period_after:
if weekday in supervisions_per_period_after[period]:
col = supervisions_per_period_after[period][weekday]
cols.append(col)
row["cols"] = cols
else:
col = None
if period in supervisions_per_period_after:
col = supervisions_per_period_after[period]
row["col"] = col
rows.append(row)
# Lesson
if period <= TimePeriod.period_max:
row = {
"type": "period",
"period": period,
"time_start": break_.before_period.time_start,
"time_end": break_.before_period.time_end,
}
if not is_person:
cols = []
for weekday in range(
TimePeriod.weekday_min, TimePeriod.weekday_max + 1
):
col = []
# Add lesson periods
if period in lesson_periods_per_period:
if weekday in lesson_periods_per_period[period]:
col += lesson_periods_per_period[period][weekday]
cols.append(col)
row["cols"] = cols
else:
col = []
# Add lesson periods
if period in lesson_periods_per_period:
col += lesson_periods_per_period[period]
row["col"] = col
rows.append(row)
return rows
def build_substitutions_list(wanted_day: date) -> List[dict]:
rows = []
subs = LessonSubstitution.objects.on_day(wanted_day).order_by(
"lesson_period__lesson__groups", "lesson_period__period"
)
for sub in subs:
if not sub.cancelled_for_teachers:
sort_a = sub.lesson_period.lesson.group_names
else:
sort_a = "Z.{}".format(sub.lesson_period.lesson.teacher_names)
row = {
"type": "substitution",
"sort_a": sort_a,
"sort_b": "{}".format(sub.lesson_period.period.period),
"el": sub,
}
rows.append(row)
# Get supervision substitutions
super_subs = SupervisionSubstitution.objects.filter(date=wanted_day)
for super_sub in super_subs:
row = {
"type": "supervision_substitution",
"sort_a": "Z.{}".format(super_sub.teacher),
"sort_b": "{}".format(super_sub.supervision.break_item.after_period_number),
"el": super_sub
}
rows.append(row)
# Sort all items
def sorter(row: dict):
return row["sort_a"] + row["sort_b"]
rows.sort(key=sorter)
return rows