module Sched; from RoomDB import RoomDB, RoomRecord, RoomType; from CourseDB import CourseDB, CourseRecord, Component; from StudentApp import Summer, Winter, Spring, Fall; from Teacher import TeacherDatabase, TeacherRecord, Monday, Tuesday, Wednesday, Thursday, Friday, Teacher_class_pref, Class, Preference_value; export Schedule, Time, section, ClassAssignment, daysOfWeek, day; object Schedule is components: ca:ClassAssignment*, cd:CourseDB, td:TeacherDatabase, rd:RoomDB, term, year, phase, department, f:fairness; description: (* This object represents a schedule in the admin portion. Schedule includes the databases used to create it. *); end Schedule; object ClassAssignment is components: tr:TeacherRecord, rr:RoomRecord, cr:CourseRecord, t:Time, s:section, staff:STAFF, tba:TBA; description: (* This object represents the connection made between a teacher, room, CourseRecord, and Time Assumes that TeacherRecord, RoomRecord, and CourseRecord are described in another RSL *); end ClassAssignment; object Time is components: h:Hour, m:Minute, d:Duration, dow:daysOfWeek; description: (* Time represents the starting time, and how long a class will go. And what days too. *); end Time; object fairness is integer description: (* A measure of how fair a schedule is. *); end fairness; object Hour is integer description: (* The time of day, to the nearest hour, in which the class starts *); end Hour; object Minute is integer description: (* The minute of the hour, in which the class starts *); end Minute; object Duration is integer description: (* How long the class will last, in minutes *); end Duration; object daysOfWeek is day* description: (* container object to hold the days in which class is in session. *); end daysOfWeek; object day is Monday or Tuesday or Wednesday or Thursday or Friday description: (* A day of the week, used to tell which days of the week a class runs for *); end day; object term is Summer or Spring or Winter or Fall description: (* container object to tell when the schedule is in effect *); end ; object year is integer description: (* We would all like to know what year it was for *); end ; object phase is integer description: (* phase 1, 2, or 3... How far along is it? *); end ; object department is string description: (* A short string identifying the department *); end ; object section is integer description: (* more than one class of a course? need section numbers to differentiate *); end ; object STAFF is boolean description: (* when a teacher can't be found, assign staff *); end ; object TBA is boolean description: (* when a room can't be found, assign TBA *); end ; operation GenerateSchedule inputs: cdb:CourseDB, TeacherDatabase, RoomDB, Schedule; outputs: sc':Schedule; post: SchedIsBest(sc') and isComplete(sc') and isAllAssigned(sc', cdb) and teachNotDB(sc') and roomNotDB(sc') and teacherProficient(sc') and roomRight(sc') and isAllUnique(sc'); description: (* GenerateSchedule is the big operation that makes many schedules and prints out the best one *); end GenerateSchedule; operation NewSchedule inputs: cdb:CourseDB, TeacherDatabase, RoomDB; outputs: sc':Schedule; post: isComplete(sc') and isAllAssigned(sc', cdb) and teachNotDB(sc') and roomNotDB(sc') and teacherProficient(sc') and roomRight(sc') and isAllUnique(sc'); description: (* NewSchedule will be the operation for when the admin user selects new from any of the various start points. *); end NewSchedule; operation fineTuneSchedule inputs: Schedule; outputs: sc':Schedule; post: isComplete(sc') and teachNotDB(sc') and roomNotDB(sc') and teacherProficient(sc') and roomRight(sc') and isAllUnique(sc'); description: (* fineTuneSchedule will be the operation for when the admin user makes edits to any of the various components. *); end NewSchedule; function isAllAssigned(sch:Schedule, CDB:CourseDB) = (forall (c:CourseRecord) if(c in CDB) then (exists (i:integer | (i >=1) and (i <= #(sch.ca))) ((sch.ca[i].cr) = c) ) ); function isComplete(sch:Schedule) = (forall (i:integer | (i >=1) and (i <= #(sch.ca))) (exists (j:integer | (j >=1) and (j <= #(sch.td.q))) (exists (k:integer | (k >=1) and (k <= #(sch.cd.cr))) (exists (l:integer | (l >=1) and (l <= #(sch.rd.rr))) ((sch.ca[i].tr = sch.td.q[j]) or sch.ca[i].staff) and sch.ca[i].cr = sch.cd.cr[k] and (sch.ca[i].rr = (sch.rd.rr[l]) or sch.ca[i].tba) )))); function teachNotDB(sch:Schedule) = (forall (ca1:ClassAssignment) (forall (ca2:ClassAssignment) ca1.t != ca2.t and ca1.tr != ca2.tr ) ); function roomNotDB(sch:Schedule) = (forall (ca3:ClassAssignment) (forall (ca4:ClassAssignment) ca3.t = ca4.t and ca3.rr = ca4.rr ) ); function teacherProficient(sch:Schedule) = (forall (i:integer | (i >=1) and (i <= #(sch.ca))) (exists (j:integer | (j >=1) and (j <= #(sch.ca))) (sch.ca[i].tr.cp.c[j].p > 0) and (sch.ca[i].tr.cp.c[j].crd = sch.ca[i].cr) )); function SchedIsBest(sch:Schedule) = (forall (sched:Schedule) sch.f >= sched.f ); function isAllUnique(sch:Schedule) = (forall (ca5:ClassAssignment) forall (ca6:ClassAssignment) ca5.cr != ca6.cr and ca5.s != ca6.s ); function roomRight(sch:Schedule) = (forall (i:integer | (i >=1) and (i <= #(sch.ca))) sch.ca[i].cr.cp = sch.ca[i].rr.rt ); end Sched;