Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 0 additions & 103 deletions campus/model/timetable.dbml

This file was deleted.

103 changes: 77 additions & 26 deletions campus/model/timetable.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
- Students and teachers involved in said lessons
- Venues

!! The schema is documented in DETAIL by the `timetable.dbml` file.
!! Commenting both files would mean duplicate documentation.
!! Please visualise it [here](https://dbml-editor.alswl.com/)!!!!
!! The tool is also able to export the schema as SQL to create the respective tables.
For all models, id is a CampusID with no relation to raw XML ID.

An allocation refers to a new set of classes, people and class timings
imported with a new timetable.
It refers to one of these:
https://github.com/nyjc-computing/nyxchange-timetable-v2/blob/data-schema/tt_file/tt_xml_docs.md
This year's timetable and last year's timetable are two seperate allocations.
The data for an allocation is stored in some .xml file, named `filename`

TODO: Update doc link after migration
"""

from typing import ClassVar
from dataclasses import dataclass, field

from campus.common import schema
from campus.common.schema.openapi import String, Integer, Boolean, DateTime
from campus.common.utils import uid

from .base import Model
Expand All @@ -30,40 +34,59 @@
"constraints": [constraints.UNIQUE],
})

## Sections that stay constant or only have additions. ##
## They will be relevant every for every allocation. ##

@dataclass(eq=False, kw_only=True)
class WeekDay(Model):
"""
Describes a day in a repeating timetable.
Assumption: This will stay constant across all allocations.

Fields:
label (String): (cosmetic purposes: 'Mon A', 'Tue A', ... 'Mon B', 'Tue B', ..., 'Sat', 'Sun')
index (Integer): index 0 is earliest (eg. Mon A), followed by Tues A, etc.
"""
id: schema.CampusID = unique_field
label: String
index: Integer
label: schema.String
index: schema.Integer


@dataclass(eq=False, kw_only=True)
class TimeSlot(Model):
"""
Timeslot which repeats across all `WeekDay`s
Assumption: This will stay constant across all allocations.

Fields:
label (String): (primarily cosmetic: '0730', '0800', ...)
start_time (DateTime): ISO8601
end_time (DateTime): ISO8601
index (Integer): index 0 is earliest slot (eg. 0730), followed by 0800 at idx 1, etc.
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
label: String
start_time: DateTime = unique_field
end_time: DateTime = unique_field
index: Integer = unique_field
label: schema.String
start_time: schema.DateTime = unique_field # ISO8601
end_time: schema.DateTime = unique_field # ISO8601
index: schema.Integer = unique_field


@dataclass(eq=False, kw_only=True)
class Venue(Model):
"""
Describes a single venue
Describes a single venue.
We have a set of venues that remain across years, except additions.
Cannot refer to a group (eg. "All science labs").

Fields:
label (String): (e.g. '03-39', 'i-Space 1', ..., follow XML when possible)
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
label: String
label: schema.String


@dataclass(eq=False, kw_only=True)
Expand All @@ -72,27 +95,44 @@ class VenueTimeSlot(Model):
Imagine each venue has its own timetable.
This is one timeslot on such a timetable, representing an intersection of
Venue and TimeSlot
We use it for clean and convenient "timetable coordinates", as
we usually reason about an intersection of venue and time anyway
Must be automatically generated for each Venue for all WeekDay, TimeSlot.

Fields:
weekday_id (CampusID): FK referencing a WeekDay.id
timeslot_id (CampusID): FK referencing a TimeSlot.id
venue_id (CampusID): FK referencing a Venue.id
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
weekday_id: schema.CampusID # FK -> weekday_id
weekday_id: schema.CampusID
timeslot_id: schema.CampusID
venue_id: schema.CampusID
__constraints__ = constraints.Unique("weekday_id", "timeslot_id", "venue_id")

## Sections that are only relevant to a specific allocation. ##
## New entries are created for each allocation. ##
## Which allocation the entry is relevant to is . ##

@dataclass(eq=False, kw_only=True)
class LessonGroup(Model):
"""
This represents a specific lesson taught to a class.
This represents a specific subject taught to a class.
Eg. Chem, taught to 2510. (eg. stored as '2510-CM')
These are labelled as an inconsistently formatted string, imported
directly from the XML. It seems we cannot seperate class and subject.

Fields:
filename (String): Allocation xml filename which this entry is relevant to
label (String): Label brought over from xml, like 2527-COM
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
filename: String
label: String
filename: schema.String
label: schema.String


@dataclass(eq=False, kw_only=True)
Expand All @@ -104,26 +144,37 @@ class LessonGroupMember(Model):
- All the students
Where each individual is one LessonGroupMember.
2510-Chem will have its own set of entries, even if the participant is duplicated.

Fields:
filename (String): Allocation xml filename which this entry is relevant to
lessongroup_id (CampusID): FK referencing a LessonGroup.id
ade_participant (String): XML id (aka TTCode or teacher_id). We have a unique mapping of these IDs
to nyjc email etc., for each allocation.
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
filename: String
lessongroup_id: String
ade_participant: String
filename: schema.String
lessongroup_id: schema.CampusID
ade_participant: schema.String
__constraints__ = constraints.Unique("lessongroup_id", "ade_participant", "filename")


@dataclass(eq=False, kw_only=True)
class Timetable(Model):
"""
A timetable represents a lesson for a LessonGroup
at some VenueTimeSlot
A timetable represents a single lesson for a LessonGroup
at some VenueTimeSlot.

Fields:
filename (String): Allocation xml filename which this entry is relevant to
lessongroup_id (CampusID): FK referencing a LessonGroup.id
venuetimeslot_id (CampusID): FK referencing a VenueTimeSlot.id
"""
id: schema.CampusID = field(default_factory=(
lambda: uid.generate_category_uid("timetable", length=8)
))
filename: String
lessongroup_id: String
venuetimeslot_id: String
filename: schema.String
lessongroup_id: schema.CampusID
venuetimeslot_id: schema.CampusID
__constraints__ = constraints.Unique("lessongroup_id", "venuetimeslot_id", "filename")