1+ import exp from 'constants' ;
12import { Request , Response } from 'express' ;
23
34import { supabase } from '../db/setupDb' ; // Supabase instance for database interactions
@@ -62,6 +63,11 @@ export interface Restriction {
6263 numDays : number ;
6364}
6465
66+ export interface GroupedOfferingList {
67+ course_id : number ;
68+ groups : Record < string , Offering [ ] > ;
69+ }
70+
6571// Interface for organizing offerings by course ID
6672export interface OfferingList {
6773 course_id : number ;
@@ -71,7 +77,7 @@ export interface OfferingList {
7177export interface CategorizedOfferingList {
7278 course_id : number ;
7379 category : 'LEC' | 'TUT' | 'PRA'
74- offerings : Offering [ ] ;
80+ offerings : Record < string , Offering [ ] > ;
7581}
7682
7783
@@ -105,14 +111,22 @@ export async function getOfferings(course_id: number, semester: string) {
105111 return offeringData ;
106112}
107113
108- // Utility function to filter valid offerings based on the provided filter
109- // function
110- export const filterValidOfferings = (
111- offerings : Offering [ ] ,
112- f : ( x : Offering ) => boolean ,
113- ) : Offering [ ] => {
114- return offerings . filter ( f ) ;
115- } ;
114+ export async function groupOfferings ( courseOfferingsList : OfferingList [ ] ) {
115+ const groupedOfferingsList : GroupedOfferingList [ ] = [ ] ;
116+ for ( const offering of courseOfferingsList ) {
117+ const groupedOfferings :
118+ GroupedOfferingList = { course_id : offering . course_id , groups : { } } ;
119+ offering . offerings . forEach ( offering => {
120+ if ( ! groupedOfferings . groups [ offering . meeting_section ] ) {
121+ groupedOfferings . groups [ offering . meeting_section ] = [ ] ;
122+ }
123+ groupedOfferings . groups [ offering . meeting_section ] . push ( offering ) ;
124+ } )
125+ groupedOfferingsList . push ( groupedOfferings ) ;
126+ }
127+
128+ return groupedOfferingsList ;
129+ }
116130
117131// Function to get the maximum number of days allowed based on restrictions
118132export async function getMaxDays ( restrictions : Restriction [ ] ) {
@@ -169,48 +183,61 @@ export function isValidOffering(
169183
170184// Function to get valid offerings by filtering them based on the restrictions
171185export async function getValidOfferings (
172- offerings : Offering [ ] ,
186+ groups : Record < string , Offering [ ] > ,
173187 restrictions : Restriction [ ] ,
174188) {
175- return filterValidOfferings (
176- offerings ,
177- ( x ) => isValidOffering ( x , restrictions ) ,
178- ) ;
189+ const validGroups : Record < string , Offering [ ] > = { } ;
190+
191+ // Loop through each group in the groups object
192+ for ( const [ groupKey , offerings ] of Object . entries ( groups ) ) {
193+ // Check if all offerings in the group are valid
194+ const allValid =
195+ offerings . every ( ( offering ) => isValidOffering ( offering , restrictions ) ) ;
196+
197+ // Only add the group to validGroups if all offerings are valid
198+ if ( allValid ) {
199+ validGroups [ groupKey ] = offerings ;
200+ }
201+ }
202+
203+ // Return the object with valid groups
204+ return validGroups ;
179205}
180206
181- export async function categorizeValidOfferings ( offerings : OfferingList [ ] ) {
207+ export async function categorizeValidOfferings (
208+ offerings : GroupedOfferingList [ ] ) {
182209 const lst : CategorizedOfferingList [ ] = [ ] ;
183210
184211 for ( const offering of offerings ) {
185212 const lectures : CategorizedOfferingList = {
186213 course_id : offering . course_id ,
187214 category : 'LEC' ,
188- offerings : [ ]
215+ offerings : { }
189216 } ;
190217 const tutorials : CategorizedOfferingList = {
191218 course_id : offering . course_id ,
192219 category : 'TUT' ,
193- offerings : [ ]
220+ offerings : { }
194221 } ;
195222 const practicals : CategorizedOfferingList = {
196223 course_id : offering . course_id ,
197224 category : 'PRA' ,
198- offerings : [ ]
225+ offerings : { }
199226 }
200227
201- for ( const entry of offering . offerings ) {
202- const meeting_section = entry . meeting_section ;
203- if ( meeting_section . startsWith ( 'PRA' ) ) {
204- practicals . offerings . push ( entry ) ;
205- } else if ( meeting_section . startsWith ( 'TUT' ) ) {
206- tutorials . offerings . push ( entry ) ;
228+ for ( const [ meeting_section , offerings ] of Object . entries (
229+ offering . groups ) ) {
230+ if ( meeting_section && meeting_section . startsWith ( 'PRA' ) ) {
231+ practicals . offerings [ meeting_section ] = offerings ;
232+ } else if ( meeting_section && meeting_section . startsWith ( 'TUT' ) ) {
233+ tutorials . offerings [ meeting_section ] = offerings ;
207234 } else {
208- lectures . offerings . push ( entry ) ;
235+ lectures . offerings [ meeting_section ] = offerings ;
209236 }
210237 }
211238
212239 for ( const x of [ lectures , practicals , tutorials ] ) {
213- if ( x . offerings . length > 0 ) {
240+ if ( Object . keys ( x . offerings ) . length > 0 ) {
214241 lst . push ( x ) ;
215242 }
216243 }
@@ -232,6 +259,12 @@ export async function canInsert(toInsert: Offering, curList: Offering[]) {
232259 return true ; // No conflict found
233260}
234261
262+ export async function canInsertList (
263+ toInsertList : Offering [ ] , curList : Offering [ ] ) {
264+ console . log ( toInsertList ) ;
265+ return toInsertList . every ( ( x ) => canInsert ( x , curList ) ) ;
266+ }
267+
235268// Function to generate a frequency table of days from a list of offerings
236269export function getFrequencyTable ( arr : Offering [ ] ) : Map < string , number > {
237270 const freqMap = new Map < string , number > ( ) ;
@@ -244,6 +277,7 @@ export function getFrequencyTable(arr: Offering[]): Map<string, number> {
244277}
245278
246279// Function to generate all valid schedules based on offerings and restrictions
280+
247281export async function getValidSchedules (
248282 validSchedules : Offering [ ] [ ] ,
249283 courseOfferingsList : CategorizedOfferingList [ ] ,
@@ -267,9 +301,11 @@ export async function getValidSchedules(
267301 const offeringsForCourse = courseOfferingsList [ cur ] ;
268302
269303 // Recursively attempt to add offerings for the current course
270- for ( const offering of offeringsForCourse . offerings ) {
271- if ( await canInsert ( offering , curList ) ) {
272- curList . push ( offering ) ; // Add offering to the current list
304+ for ( const [ groupKey , offerings ] of Object . entries (
305+ offeringsForCourse . offerings ) ) {
306+ if ( await canInsertList ( offerings , curList ) ) {
307+ const count = offerings . length ;
308+ curList . push ( ...offerings ) ; // Add offering to the current list
273309
274310 // Recursively generate schedules for the next course
275311 await getValidSchedules (
@@ -282,7 +318,7 @@ export async function getValidSchedules(
282318 ) ;
283319
284320 // Backtrack: remove the last offering if no valid schedule was found
285- curList . pop ( ) ;
321+ for ( let i = 0 ; i < count ; i ++ ) curList . pop ( ) ;
286322 }
287323 }
288324}
@@ -294,9 +330,9 @@ export default {
294330 // Extract event details and course information from the request
295331 const { name, date, semester, search, courses, restrictions} = req . body ;
296332 const courseOfferingsList : OfferingList [ ] = [ ] ;
297- const validCourseOfferingsList : OfferingList [ ] = [ ] ;
333+ const validCourseOfferingsList : GroupedOfferingList [ ] = [ ] ;
298334 const maxdays = await getMaxDays ( restrictions ) ;
299-
335+ const validSchedules : Offering [ ] [ ] = [ ] ;
300336 // Fetch offerings for each course
301337 for ( const course of courses ) {
302338 const { id} = course ;
@@ -306,27 +342,25 @@ export default {
306342 } ) ;
307343 }
308344
345+ const groupedOfferingsList : GroupedOfferingList [ ] =
346+ await groupOfferings ( courseOfferingsList ) ;
347+
348+ // console.log(JSON.stringify(groupedOfferingsList, null, 2));
349+
309350 // Filter out invalid offerings based on the restrictions
310- for ( const { course_id, offerings } of courseOfferingsList ) {
351+ for ( const { course_id, groups } of groupedOfferingsList ) {
311352 validCourseOfferingsList . push ( {
312353 course_id : course_id ,
313- offerings : await getValidOfferings ( offerings ?? [ ] , restrictions ) ,
354+ groups : await getValidOfferings ( groups , restrictions ) ,
314355 } ) ;
315356 }
316357
317- // Log course offerings (for debugging purposes)
318- /*validCourseOfferingsList.forEach(
319- (course) => console.log(JSON.stringify(course, null, 2)),
320- );*/
321-
322358 const categorizedOfferings =
323359 await categorizeValidOfferings ( validCourseOfferingsList ) ;
360+
324361 // console.log(typeof categorizedOfferings);
325362 // console.log(JSON.stringify(categorizedOfferings, null, 2));
326363
327-
328- const validSchedules : Offering [ ] [ ] = [ ] ;
329-
330364 // Generate valid schedules for the given courses and restrictions
331365 await getValidSchedules (
332366 validSchedules ,
0 commit comments