@@ -3,7 +3,66 @@ import {Request, Response} from 'express';
33import { supabase } from '../db/setupDb' ;
44import asyncHandler from '../middleware/asyncHandler' ;
55
6- async function getOfferings ( course_id : number , semester : string ) {
6+ export interface Offering {
7+ id : number ;
8+ course_id : number ;
9+ meeting_section : string ;
10+ offering : string ;
11+ day : string ;
12+ start : string ;
13+ end : string ;
14+ location : string ;
15+ current : number ;
16+ max : number ;
17+ is_waitlisted : boolean ;
18+ delivery_mode : string ;
19+ instructor : string ;
20+ notes : string ;
21+ code : string ;
22+ }
23+
24+ export function createOffering ( overrides : Partial < Offering > = { } ) : Offering {
25+ return {
26+ id : overrides . id ?? - 1 ,
27+ course_id : overrides . course_id ?? - 1 ,
28+ meeting_section : overrides . meeting_section ?? 'No Section' ,
29+ offering : overrides . offering ?? 'No Offering' ,
30+ day : overrides . day ?? 'N/A' ,
31+ start : overrides . start ?? '00:00:00' ,
32+ end : overrides . end ?? '00:00:00' ,
33+ location : overrides . location ?? 'No Room' ,
34+ current : overrides . current ?? - 1 ,
35+ max : overrides . max ?? - 1 ,
36+ is_waitlisted : overrides . is_waitlisted ?? false ,
37+ delivery_mode : overrides . delivery_mode ?? 'N/A' ,
38+ instructor : overrides . instructor ?? 'N/A' ,
39+ notes : overrides . notes ?? 'N/A' ,
40+ code : overrides . code ?? 'N/A' ,
41+ } ;
42+ }
43+
44+ export enum RestrictionType {
45+ RestrictBefore = 'Restrict Before' ,
46+ RestrictAfter = 'Restrict After' ,
47+ RestrictBetween = 'Restrict Between' ,
48+ RestrictDay = 'Restrict Day' ,
49+ RestrictDaysOff = 'Days Off'
50+ }
51+
52+ export interface Restriction {
53+ type : RestrictionType ;
54+ days : string [ ] ;
55+ startTime : string ;
56+ endTime : string ;
57+ disabled : boolean ;
58+ }
59+
60+ export interface OfferingList {
61+ course_id : number ;
62+ offerings : Offering [ ] ;
63+ }
64+
65+ export async function getOfferings ( course_id : number , semester : string ) {
766 let { data : offeringData , error : offeringError } = await supabase
867 . schema ( 'course' )
968 . from ( 'offerings' )
@@ -29,23 +88,123 @@ async function getOfferings(course_id: number, semester: string) {
2988}
3089
3190
91+
92+ export const filterValidOfferings =
93+ ( offerings : Offering [ ] , f : ( x : Offering ) => boolean ) :
94+ Offering [ ] => {
95+ return offerings . filter ( f ) ;
96+ }
97+
98+ export function isValidOffering (
99+ offering : Offering , restrictions : Restriction [ ] ) {
100+ for ( const restriction of restrictions ) {
101+ if ( restriction . disabled ) continue ;
102+
103+ switch ( restriction . type ) {
104+ case RestrictionType . RestrictBefore :
105+ if ( offering . start < restriction . startTime ) return false ;
106+ break ;
107+
108+ case RestrictionType . RestrictAfter :
109+ if ( offering . end > restriction . endTime ) return false ;
110+ break ;
111+
112+ case RestrictionType . RestrictBetween :
113+ if ( offering . start >= restriction . startTime &&
114+ offering . end <= restriction . endTime ) {
115+ return false ;
116+ }
117+ break ;
118+ case RestrictionType . RestrictDay :
119+ if ( restriction . days . includes ( offering . day ) ) {
120+ return false ;
121+ }
122+ break ;
123+ }
124+ }
125+ return true ;
126+ }
127+
128+ export async function getValidOfferings (
129+ offerings : Offering [ ] , restrictions : Restriction [ ] ) {
130+ return filterValidOfferings ( offerings , x => isValidOffering ( x , restrictions ) ) ;
131+ }
132+
133+ export async function canInsert ( toInsert : Offering , curList : Offering [ ] ) {
134+ for ( const offering of curList ) {
135+ if ( offering . day == toInsert . day ) {
136+ if ( offering . start < toInsert . end && toInsert . start < offering . end ) {
137+ return false ;
138+ }
139+ }
140+ }
141+
142+ return true ;
143+ }
144+
145+ export async function getValidSchedules (
146+ courseOfferingsList : OfferingList [ ] , curList : Offering [ ] , cur : number ,
147+ len : number ) :
148+ Promise < Offering [ ] [ ] > {
149+ if ( cur == len ) return [ curList ] ;
150+
151+ const validSchedules : Offering [ ] [ ] = [ ] ;
152+
153+ const offeringsForCourse = courseOfferingsList [ cur ] ;
154+
155+ for ( const offering of offeringsForCourse . offerings ) {
156+ if ( await canInsert ( offering , curList ) ) {
157+ curList . push ( offering ) ;
158+ // Recursively call the function for the next course
159+ const res : Offering [ ] [ ] = await getValidSchedules (
160+ courseOfferingsList , curList , cur + 1 , len ) ;
161+
162+ // If a valid schedule is found, return it
163+ validSchedules . push ( ...res ) ;
164+
165+ // If no valid schedule is found, pop the offering and continue
166+ curList . pop ( ) ;
167+ }
168+ }
169+
170+ // If no valid schedule is found for this course, return null
171+ return validSchedules ;
172+ }
173+
32174export default {
33175 generateTimetable : asyncHandler ( async ( req : Request , res : Response ) => {
34176 try {
35177 // Retrieve event properties from the request body
36178 const { name, date, semester, search, courses, restrictions} = req . body ;
37- const courseOfferingsList = [ ] ;
179+ const courseOfferingsList : OfferingList [ ] = [ ] ;
180+ const validCourseOfferingsList : OfferingList [ ] = [ ] ;
38181 // Retrieve the authenticated user
39182 const user_id = ( req as any ) . user . id ;
40183
41184 // extracting offerings from each course
42185 for ( const course of courses ) {
43186 const { id, code, name} = course ;
44187 courseOfferingsList . push (
45- { course_id : id , offerings : await getOfferings ( id , semester ) } ) ;
188+ { course_id : id , offerings : await getOfferings ( id , semester ) ?? [ ] } ) ;
46189 }
190+ courseOfferingsList . forEach (
191+ course => console . log ( JSON . stringify ( course , null , 2 ) ) ) ;
47192
48- return res . status ( 200 ) . json ( courseOfferingsList ) ;
193+ // filter out invalid course entries
194+ for ( const { course_id, offerings} of courseOfferingsList ) {
195+ validCourseOfferingsList . push ( {
196+ course_id : course_id ,
197+ offerings : await getValidOfferings ( offerings ?? [ ] , restrictions )
198+ } ) ;
199+ }
200+
201+ const validSchedules = await getValidSchedules (
202+ validCourseOfferingsList , [ ] , 0 , validCourseOfferingsList . length ) ;
203+
204+ if ( validSchedules . length === 0 ) {
205+ return res . status ( 404 ) . json ( { error : 'No valid schedules found.' } ) ;
206+ }
207+ return res . status ( 200 ) . json ( { validSchedules} ) ;
49208 } catch ( error ) {
50209 return res . status ( 500 ) . send ( { error} ) ;
51210 }
0 commit comments