fried my mind thinking of this, needs testing and extra work
This commit is contained in:
1 file changed
+93
-4
+93
-4
@@ -13,8 +13,12 @@
|
|||||||
const char FLEX[2][11] = {"XAT--12A-S", "XAT--12B-S"};
|
const char FLEX[2][11] = {"XAT--12A-S", "XAT--12B-S"};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// 0-9 block idx | CRS_NO_ID | pupilNums
|
uint8_t numberOfClasses;
|
||||||
uint16_t timetable[TOTAL_BLOCKS][MAX_COURSE_ID_LEN][CLASS_CAP];
|
char classes[CLASSROOMS][MAX_COURSE_ID_LEN];
|
||||||
|
} TIMETABLE_BLOCK;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TIMETABLE_BLOCK timetable[TOTAL_BLOCKS];
|
||||||
bool success;
|
bool success;
|
||||||
} TIMETABLE;
|
} TIMETABLE;
|
||||||
|
|
||||||
@@ -46,11 +50,28 @@ uint8_t *equal(uint8_t *arr, size_t size) {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FirstToSecondSemester,
|
||||||
|
SecondToFirstSemester
|
||||||
|
} StepType;
|
||||||
|
|
||||||
|
int stepIndex(int offset, StepType type, uint8_t blocksPerSemester) {
|
||||||
|
if (type == FirstToSecondSemester)
|
||||||
|
return (offset == 0 || offset == -1 * (blocksPerSemester - 1)) ? blocksPerSemester : (-1 * (blocksPerSemester - 1));
|
||||||
|
|
||||||
|
if (type == SecondToFirstSemester)
|
||||||
|
return (offset == 0 || offset == blocksPerSemester + 1) ? (-1 * blocksPerSemester) : (blocksPerSemester + 1);
|
||||||
|
|
||||||
|
// Should not be possible
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
TIMETABLE generateTimetable(STUDENT *students, size_t size_students, COURSE *courses, size_t size_courses) {
|
TIMETABLE generateTimetable(STUDENT *students, size_t size_students, COURSE *courses, size_t size_courses) {
|
||||||
TIMETABLE timetable = {{{{0}}}, false};
|
TIMETABLE_BLOCK defaultBlock = {0, {"\0"}};
|
||||||
|
TIMETABLE timetable = {{defaultBlock}, false};
|
||||||
|
|
||||||
uint8_t MEDIAN = floor((float) (MIN_REQ + CLASS_CAP) / 2);
|
uint8_t MEDIAN = floor((float) (MIN_REQ + CLASS_CAP) / 2);
|
||||||
// uint8_t BLOCKS_PER_SEMESTER = TOTAL_BLOCKS / 2;
|
uint8_t BLOCKS_PER_SEMESTER = TOTAL_BLOCKS / 2;
|
||||||
|
|
||||||
|
|
||||||
/*** STEP 1 - Tally requests to check which courses are eligable to run ***/
|
/*** STEP 1 - Tally requests to check which courses are eligable to run ***/
|
||||||
@@ -385,6 +406,74 @@ TIMETABLE generateTimetable(STUDENT *students, size_t size_students, COURSE *cou
|
|||||||
free(currentInserted);
|
free(currentInserted);
|
||||||
free(tempStudents);
|
free(tempStudents);
|
||||||
|
|
||||||
|
/*** STEP 4 - Insert classes into timetable ***/
|
||||||
|
while (activeCoursesLen > 0) {
|
||||||
|
// Find highest resource class (most times run)
|
||||||
|
size_t index = 0;
|
||||||
|
uint8_t max = 0;
|
||||||
|
for (size_t i = 0; i < activeCoursesLen; i++) {
|
||||||
|
if (allClassRunCounts[i] > max) {
|
||||||
|
max = allClassRunCounts[i];
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char course[MAX_COURSE_NO_LEN] = {"\0"};
|
||||||
|
strcpy(course, courses[activeCoursesIndexes[index]].crsNo);
|
||||||
|
|
||||||
|
// Tally first semester and second semester
|
||||||
|
uint8_t *allSemesterBlockLens = malloc(TOTAL_BLOCKS * sizeof(uint8_t));
|
||||||
|
for (uint8_t i = 0; i < TOTAL_BLOCKS; i++)
|
||||||
|
allSemesterBlockLens[i] = timetable.timetable[i].numberOfClasses;
|
||||||
|
|
||||||
|
// If there is more than one class running
|
||||||
|
if (allClassRunCounts[activeCoursesIndexes[index]] > 1) {
|
||||||
|
// Get index of block with least class run counts
|
||||||
|
uint8_t minClassrooms = CLASSROOMS;
|
||||||
|
uint8_t blockIndex = 0; // default to first block if all are same
|
||||||
|
for (uint8_t i = 0; i < TOTAL_BLOCKS; i++) {
|
||||||
|
if (allSemesterBlockLens[i] < minClassrooms) {
|
||||||
|
minClassrooms = allSemesterBlockLens[i];
|
||||||
|
blockIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StepType step = blockIndex < BLOCKS_PER_SEMESTER ? FirstToSecondSemester : SecondToFirstSemester;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
// Disperse classes throughout both semesters
|
||||||
|
for (size_t i = 0; i < allClassRunCounts[index]; i++) {
|
||||||
|
char className[MAX_COURSE_ID_LEN] = {"\0"};
|
||||||
|
strcpy(className, classes[activeCoursesIndexes[index]].crsNo);
|
||||||
|
bool classInserted = false;
|
||||||
|
|
||||||
|
while (!classInserted) {
|
||||||
|
blockIndex += offset;
|
||||||
|
|
||||||
|
if (timetable.timetable[blockIndex].numberOfClasses < CLASSROOMS) {
|
||||||
|
uint8_t classIndex = timetable.timetable[blockIndex].numberOfClasses;
|
||||||
|
strcpy(timetable.timetable[blockIndex].classes[blockIndex], className);
|
||||||
|
allClassRunCounts[index]--;
|
||||||
|
classInserted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = stepIndex(offset, step, BLOCKS_PER_SEMESTER);
|
||||||
|
|
||||||
|
if (blockIndex >= (TOTAL_BLOCKS - 1)) {
|
||||||
|
blockIndex = step == FirstToSecondSemester ? 0 : BLOCKS_PER_SEMESTER;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the class only runs once, place in semester with least classes
|
||||||
|
} else if (allClassRunCounts[activeCoursesIndexes[index]] == 1) {
|
||||||
|
// TODO: handle this
|
||||||
|
}
|
||||||
|
|
||||||
|
free(allSemesterBlockLens);
|
||||||
|
}
|
||||||
|
|
||||||
// DO MORE ALGORITHM
|
// DO MORE ALGORITHM
|
||||||
|
|
||||||
free(classes);
|
free(classes);
|
||||||
|
|||||||
Reference in new issue
Block a user