Skip to content

Commit 1c4f822

Browse files
committed
lectures with multiple timestamps is now considered
1 parent 794137b commit 1c4f822

File tree

1 file changed

+76
-42
lines changed

1 file changed

+76
-42
lines changed

course-matrix/backend/src/controllers/generatorController.ts

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import exp from 'constants';
12
import {Request, Response} from 'express';
23

34
import {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
6672
export interface OfferingList {
6773
course_id: number;
@@ -71,7 +77,7 @@ export interface OfferingList {
7177
export 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
118132
export 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
171185
export 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
236269
export 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+
247281
export 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

Comments
 (0)