//------------------------------------------------------------------------------ // initializes machineNodes // // //------------------------------------------------------------------------------ /*private void InitMachineNodes() * { * for (int i = 1; i <= QUARTERS; i++) * { * MachineNode m = new MachineNode(0, i); * machineNodes.Add(m); * } * }*/ private void InitializeMachineNodes() { if (quarters < yearlength) { for (int i = 1; i <= quarters; i++) { MachineNode m = new MachineNode(0, i); machineNodes.Add(m); } } else { int quarterCount = 0; while (quarterCount < quarters) { for (int i = 0; i <= years; i++) { for (int j = 1; j <= yearlength; j++) { MachineNode m = new MachineNode(i, j); machineNodes.Add(m); quarterCount++; if (quarterCount >= quarters) { break; } } } } } }
//------------------------------------------------------------------------------ // initializes machineNodes // // //------------------------------------------------------------------------------ private void InitMachineNodes() { for (int i = 1; i <= QUARTERS; i++) { MachineNode m = new MachineNode(0, i); machineNodes.Add(m); } }
//------------------------------------------------------------------------------ // does the actual action of putting a course on a machine; this will be the hub // for implementing preferences, not all are implemented at the moment; also, // right now unscheduled courses are simply going into a list but if you were to // do something else, this function is where it would originate //------------------------------------------------------------------------------ private void PutCourseOnMachine(Job j, List <CourseNode> groups) { //get most recent prereq int mostRecentPrereqYear = 0; int mostRecentPrereqQuarter = 1; int start = 0; //if no prereqs then schedule at any time if (PrereqsExist(groups)) //this is if there are prereqs { int[] yq = GetMostRecentPrereq(groups); mostRecentPrereqYear = yq[0]; mostRecentPrereqQuarter = yq[1]; if (mostRecentPrereqQuarter == -1 || mostRecentPrereqYear == -1) //has prerequisites but they weren't able to be scheduled { unableToSchedule.Add(j); return; } //schedule 1 or more quarters after, mind the year //schedule on nearest available machine //start i at whatever quarter you calculate, not simply zero start = (mostRecentPrereqYear * 4 + mostRecentPrereqQuarter - 1) + 1; } for (int i = start; i < machineNodes.Count; i++) { MachineNode mn = machineNodes[i]; //if machine node exeeds preferences continue to next node if (mn.GetClassesScheduled() > 3) { continue; } List <Machine> machines = mn.GetMachines(); for (int k = 0; k < machines.Count; k++) { Machine m = machines[k]; if (m.CanDoJob(j) && !m.CheckInUse()) //if not in use and it can do the job { if (Overlap(j, m, mn)) //can't schedule it if the times overlap even if machine found { continue; } m.SetCurrentJobProcessing(j); m.SetInUse(true); j.SetScheduled(true); j.SetQuarterScheduled(m.GetQuarter()); j.SetYearScheduled(m.GetYear()); mn.AddClassesScheduled(1); finalPlan.Add(m); return; } } } }
//------------------------------------------------------------------------------ // AN ERROR CHECKING METHOD TO PREVENT CLASSES FROM HAPPENING DURING THE SAME TIME // check to see if a job overlaps with another job's times in a single // MachineNode; can't be in 2 places at once you know? //------------------------------------------------------------------------------ private bool Overlap(Job j, Machine goal, MachineNode mn) { bool flag = false; //Defaulted to continue //need list of all the start and end times from goal List <DayTime> dt = goal.GetDateTime(); List <Machine> myMachines = mn.GetAllScheduledMachines(); //Look for Scheduled Courses in All Quarters for (int i = 0; i < myMachines.Count; i++) { Machine m = myMachines[i]; List <DayTime> tempDT = m.GetDateTime(); //Each class is available for the same amount of days if (dt.Count == tempDT.Count) { for (int k = 0; k < dt.Count; k++) { //Checks to see if the start time or end time exists between the start and end of a scheduled course if ((dt[k].GetStartTime() >= tempDT[k].GetStartTime() && dt[k].GetStartTime() <= tempDT[k].GetEndTime()) || (dt[k].GetEndTime() >= tempDT[k].GetStartTime() && dt[k].GetEndTime() <= tempDT[k].GetEndTime())) { flag = true; } } } else { int min = Math.Min(dt.Count, tempDT.Count); //Which class starts earlier //Compares the courses for the day they are taken on if (dt.Count == min) { flag = compareDays(dt, tempDT); } else { flag = compareDays(tempDT, dt); } if (flag) { return(flag); } } } return(flag); }
void addMachine(Machine dummyMachine, int course) { dummyMachine.AddJob(new Job(course)); //adds job for (int i = 0; i < machineNodes.Count; i++) { MachineNode mn = machineNodes[i]; List <Machine> machines = mn.GetMachines(); if (machines.Count > 0) { for (int j = 0; j < machines.Count; j++) { Machine m = machines[j]; if (m == dummyMachine) { //found the machine, just add job m.AddJob(new Job(course)); break; } else if (dummyMachine.GetYear().Equals(mn.GetYear()) && dummyMachine.GetQuarter().Equals(mn.GetQuarter())) { //machine does not exist, add it in machines.Add(dummyMachine); break; } } } else if (dummyMachine.GetYear().Equals(mn.GetYear()) && dummyMachine.GetQuarter().Equals(mn.GetQuarter())) { machines.Add(dummyMachine); break; } else //in the instance that machines == 0 and either year or quarter were different { //NOTE: This isn't so much an error as a bookkeeping check. Because CourseTime contains only 1 year // machines dated beyond the first year throw this error. So this is a database issue. /* * Console.WriteLine("Dummy Machine Year: " + dummyMachine.GetYear()); * Console.WriteLine("Dummy Machine Quarter: " + dummyMachine.GetQuarter()); * Console.WriteLine("Dummy Course ID: " + course); * Console.WriteLine("mn Year: " + mn.GetYear()); * Console.WriteLine("mn Quarter: " + mn.GetQuarter()); * Console.WriteLine('\n'); */ } } }
//------------------------------------------------------------------------------ // // check to see if a job overlaps with another job's times in a single // MachineNode; can't be in 2 places at once you know? //------------------------------------------------------------------------------ private bool Overlap(Job j, Machine goal, MachineNode mn) { bool flag = false; //need list of all the start and end times from goal List <DayTime> dt = goal.GetDateTime(); List <Machine> myMachines = mn.GetAllScheduledMachines(); for (int i = 0; i < myMachines.Count; i++) { Machine m = myMachines[i]; List <DayTime> tempDT = m.GetDateTime(); if (dt.Count == tempDT.Count) { for (int k = 0; k < dt.Count; k++) { if ((dt[k].GetStartTime() >= tempDT[k].GetStartTime() && dt[k].GetStartTime() <= tempDT[k].GetEndTime()) || (dt[k].GetEndTime() >= tempDT[k].GetStartTime() && dt[k].GetEndTime() <= tempDT[k].GetEndTime())) { return(true); } } } else { int min = Math.Min(dt.Count, tempDT.Count); if (dt.Count == min) { flag = compareDays(dt, tempDT); } else { flag = compareDays(tempDT, dt); } if (flag) { return(flag); } } } return(flag); }
//------------------------------------------------------------------------------ // temporary until we have more data, better data // // //------------------------------------------------------------------------------ private void InitYearTwo() { //init more machine nodes for the next year for (int i = 1; i <= QUARTERS; i++) { MachineNode m = new MachineNode(1, i); machineNodes.Add(m); } //transfer all the same classes to the set of machine nodes for (int i = 4; i < 8; i++) { MachineNode oldMn = machineNodes[i - 4]; MachineNode newMn = machineNodes[i]; for (int j = 0; j < oldMn.GetMachines().Count; j++) { Machine oldMachine = oldMn.GetMachines()[j]; Machine newMachine = new Machine(oldMachine); newMachine.SetYear(1); newMn.AddMachine(newMachine); } } }
void normalizeMachines() { //transfer all the same classes to the set of machine nodes if (quarters >= yearlength) { for (int i = yearlength; i < quarters; i++) { MachineNode oldMn = machineNodes[i % yearlength]; MachineNode newMn = machineNodes[i]; for (int j = 0; j < oldMn.GetMachines().Count; j++) { Machine oldMachine = oldMn.GetMachines()[j]; Machine newMachine = new Machine(oldMachine); newMachine.SetYear(i / yearlength); newMn.AddMachine(newMachine); } } return; } else { return; } }
//------------------------------------------------------------------------------ // create a query that will pull all the different machines // which means getting every single time slot // distinct year, quarter, time, and set of DayTimes //------------------------------------------------------------------------------ private void InitMachines() { string query = "select CourseID, StartTimeID, EndTimeID, DayID, QuarterID, SectionID from CourseTime order by CourseID ASC;"; DataTable dt = ExecuteQuery(query); Machine dummyMachine = new Machine(); DayTime dummyDayTime = new DayTime(); int dt_size = dt.Rows.Count - 1; DataRow dr = dt.Rows[dt_size]; int currentCourse = (int)dr.ItemArray[0]; int currentQuarter = (int)dr.ItemArray[4]; int currentSection = (int)dr.ItemArray[5]; int course = 0; int start = 0; int end = 0; int day = 0; int quarter = 0; int section = 0; while (dt_size >= 0) { dr = dt.Rows[dt_size]; //check for null values if (dr.ItemArray[0] == DBNull.Value || dr.ItemArray[1] == DBNull.Value || dr.ItemArray[2] == DBNull.Value || dr.ItemArray[3] == DBNull.Value || dr.ItemArray[4] == DBNull.Value || dr.ItemArray[5] == DBNull.Value) { dt_size--; continue; } course = (int)dr.ItemArray[0]; section = (int)dr.ItemArray[5]; quarter = (int)dr.ItemArray[4]; //going to have to do the same with year probably //same course but different section is a different machine //different course is a different machine if ((currentCourse == course && (currentSection != section || currentQuarter != quarter)) || (currentCourse != course)) { dummyMachine = new Machine(); currentCourse = (int)dr.ItemArray[0]; currentSection = (int)dr.ItemArray[5]; currentQuarter = (int)dr.ItemArray[4]; } start = (int)dr.ItemArray[1]; end = (int)dr.ItemArray[2]; day = (int)dr.ItemArray[3]; dummyDayTime = new DayTime(); dummyDayTime.SetDayTime(day, start, end); dummyMachine.AddDayTime(dummyDayTime); dummyMachine.SetQuarter(quarter); //we add a new machine when we peek to the next row and see //(different course) OR (same course and (different section OR dif qtr)) if (dt_size == 0 || ((int)dt.Rows[dt_size - 1].ItemArray[0] != currentCourse || ((int)dt.Rows[dt_size - 1].ItemArray[0] == currentCourse && ((int)dt.Rows[dt_size - 1].ItemArray[5] != currentSection) || (int)dt.Rows[dt_size - 1].ItemArray[4] != currentQuarter))) { dummyMachine.AddJob(new Job(course)); for (int i = 0; i < machineNodes.Count; i++) { MachineNode mn = machineNodes[i]; List <Machine> machines = mn.GetMachines(); if (machines.Count > 0) { for (int j = 0; j < machines.Count; j++) { Machine m = machines[j]; if (m == dummyMachine) //found the machine, just add job { m.AddJob(new Job(course)); } else if (dummyMachine.GetYear().Equals(mn.GetYear()) && dummyMachine.GetQuarter().Equals(mn.GetQuarter())) //machine does not exist, add it in { machines.Add(dummyMachine); break; } } } else if (dummyMachine.GetYear().Equals(mn.GetYear()) && dummyMachine.GetQuarter().Equals(mn.GetQuarter())) { machines.Add(dummyMachine); break; } else { Console.WriteLine("Dummy Machine Year: " + dummyMachine.GetYear()); Console.WriteLine("Dummy Machine Quarter: " + dummyMachine.GetQuarter()); Console.WriteLine("mn Year: " + mn.GetYear()); Console.WriteLine("mn Quarter: " + mn.GetQuarter()); Console.WriteLine('\n'); } } } dt_size--; } //print machines for testing; unnecessary for (int i = 0; i < machineNodes.Count; i++) { MachineNode mn = machineNodes[i]; List <Machine> machines = mn.GetMachines(); Console.WriteLine("Quarter: " + mn.GetQuarter()); for (int j = 0; j < machines.Count; j++) { Machine m = machines[j]; m.Print(); } } }
//------------------------------------------------------------------------------ // Puts a course into the schedule by first checking the course's most // immediate prerequisite that has been scheduled and starting from the next // nearest schedulable machineNode. From the starting point the course is then // scheduled according to preferences. // // SPECIAL NOTE: As Polina writes below, this is indeed a perfect function to // implement several preferences invloved with courses and scheduling. // Namely, Courses per quarter, day preferences, and timeOfDay preferences. // I took the liberty of labeling the best spots to place these. // Additionally, should Machines ever have a CoreCourse, or other attributes // (Diversity, Humanities, etc.) checks could be placed in this function // to schedule those courses. // // does the actual action of putting a course on a machine; this will be the hub // for implementing preferences, not all are implemented at the moment; also, // right now unscheduled courses are simply going into a list but if you were to // do something else, this function is where it would originate //------------------------------------------------------------------------------ private void PutCourseOnMachine(Job j, List <CourseNode> groups) { #region variables //get most recent prereq int mostRecentPrereqYear = 0; int mostRecentPrereqQuarter = 1; int start = 0; #endregion #region Prerequisite Handler //if no prereqs then schedule at any time if (PrereqsExist(groups)) //CHECKS FOR NULL { //this is if there are prereqs int[] yq = GetMostRecentPrereq(groups); mostRecentPrereqYear = yq[0]; mostRecentPrereqQuarter = yq[1]; //ERROR CHECK if (mostRecentPrereqQuarter == -1 || mostRecentPrereqYear == -1) { //has prerequisites but they weren't able to be scheduled unableToSchedule.Add(j); return; } //schedule 1 or more quarters after, mind the year <--(?) //schedule on nearest available machine //start i at whatever quarter you calculate, not simply zero start = (mostRecentPrereqYear * 4 + mostRecentPrereqQuarter - 1) + 1; } #endregion for (int i = start; i < machineNodes.Count; i++) { MachineNode mn = machineNodes[i]; // Check the number of credits scheduled per quarter make sure it does not exceed preference. // Check the number of core credits scheduled per quarter make sure it does not exceed preference. // TODO: Add a default case. What if they dont have a preference should we assign all their classes in one quarter? // Probably not... //System.Diagnostics.Debug.WriteLine("NUM OF CREDITS FOR JOB: " + j.GetNumCredits() + " CORE COURSE: " + j.GetCoreCourse()); if (mn.GetCreditsScheduled() + j.GetNumCredits() > preferences.getCreditsPerQuarter() || (j.GetCoreCourse() && j.GetNumCredits() + mn.GetMajorCreditsScheduled() > preferences.getCoreCredits())) { continue; } List <Machine> machines = mn.GetMachines(); for (int k = 0; k < machines.Count; k++) { //<<----------------------------INSERT DAY/TIME PREFERENCE AND CHECK AGAINST IT Machine m = machines[k]; if (m.CanDoJob(j) && !m.CheckInUse()) { //if not in use and it can do the job if (Overlap(j, m, mn)) { //can't schedule it if the times overlap even if machine found continue; } m.SetCurrentJobProcessing(j); m.SetInUse(true); j.SetScheduled(true); j.SetQuarterScheduled(m.GetQuarter()); j.SetYearScheduled(m.GetYear()); // Need to update the machine node such that it reflects the new amount of credits, core credits, etc. //mn.AddClassesScheduled(1); mn.AddClassesScheduled(j); finalPlan.Add(m); return; } } } }