/* Called when the submit button is clicked. Initiliazes some data and starts the schedule * generation process. */ private void btnSubmit_Click(object sender, RoutedEventArgs e) { //Clear all of the generated tabs tabBase.SelectedIndex = 0; for (int tabIter = (tabBase.Items.Count-1); tabIter > 1; tabIter--) { tabBase.Items.RemoveAt(tabIter); } totalClassCount = lstFinalClasses.Items.Count; currentClassRunning = 0; possibleSections = new List<ClassSection>(); //All of the possible courses confirmedSections = new List<List<ClassSection>>(); progress.Value = 0; //Reset the progress bar tabCount = 0; //Reset the tab numberings. secondsRemaining = 0; //Reset timeleft sectionsInGrid = new Dictionary<Grid, List<ClassSection>>(); //Reset the grid dictionary //Start finding bitstrings in the background BackgroundWorker bitstringworker = new BackgroundWorker(); bitstringworker.WorkerSupportsCancellation = false; bitstringworker.WorkerReportsProgress = true; bitstringworker.DoWork += new DoWorkEventHandler(generateAllBitStrings); bitstringworker.ProgressChanged += new ProgressChangedEventHandler(reportProgress); //Count how many courses there are so we know how many bitstrings to generate int totalCourses = 0; const int MAXCOURSES = 23; Random randomGen = new Random(); foreach (DepartmentClass finalClass in lstFinalClasses.Items) { //Random number of courses to pick from: // Take max courses. Remove the courses we have already. Make sure one section is leftover for the last class. int randomNumberOfSectionsFromThisClass = 0; if (finalClass != lstFinalClasses.Items.Last()) { randomNumberOfSectionsFromThisClass = (int)Math.Round(randomGen.NextDouble() * (MAXCOURSES - totalCourses - 1)); } else { randomNumberOfSectionsFromThisClass = MAXCOURSES - totalCourses; } foreach (ClassSection section in finalClass.sections) { //If course is not in exlusions if (!section.excluded) { //temporary crappy code to fill in the parent class information for sections section.parentClass = finalClass.ToString(); //end temporary crappy code } } List<ClassSection> possible = pickSections(finalClass, randomNumberOfSectionsFromThisClass, randomGen); MyStopwatch timeout = new MyStopwatch(); timeout.start(); while (!allLinksPresent(possible) && !ignoreLinks) { if (!limitRandom) { YesNoPopup popupLinkRemoved = new YesNoPopup("You have excluded a linked section in " + possible[0].parentClass + ".\nWould you like to exclude the sections that require it?"); popupLinkRemoved.show(); popupLinkRemoved.onYes = delegate { removeMissingLinks(possible); btnSubmit_Click(sender, e); }; popupLinkRemoved.onNo = delegate { ignoreLinks = true; btnSubmit_Click(sender, e); }; return; } possible = pickSections(finalClass, randomNumberOfSectionsFromThisClass); // After 2 seconds, just try submitting again in case there's a situation where // there's not enough random sections to pick all the links. IE: 3 linked, but only allowed 2 if (timeout.stop() > 2000) { btnSubmit_Click(sender, e); return; } //Slow down the repetitions - gives a little more randomness. Thread.Sleep(100); } totalCourses += possible.Count; foreach (ClassSection section in possible) { possibleSections.Add(section); } } if (totalCourses < 1) { InfoPopup popupNoCourses = new InfoPopup("There are 0 sections included!"); popupNoCourses.show(); } //Start counting down. counterDown = new BackgroundWorker(); counterDown.WorkerSupportsCancellation = true; counterDown.WorkerReportsProgress = false; counterDown.DoWork += new DoWorkEventHandler(decreaseTimeRemaining); counterDown.RunWorkerAsync(); //Start generating bitstrings in background bitstringworker.RunWorkerAsync("" + totalCourses); //Disable the submit button while we're generating. btnSubmit.IsEnabled = false; //Reset link ignore ignoreLinks = false; }
/* Called when the bitstring worker reports progress. * Should update the GUI to reflect schedules that work */ private void reportProgress(object sender, ProgressChangedEventArgs e) { if (e.ProgressPercentage == 100) { btnSubmit.IsEnabled = true; //Reenable the submit button now that we're (mostly) done. tabBase.Items.Add(tabResults); lblResultCount.Content = "You have " + confirmedSections.Count + " results!"; lblResultCount.FontSize = 17.0; tabResults.Visibility = System.Windows.Visibility.Visible; cResultStart.Items.Clear(); for (int i = 0; i < confirmedSections.Count; i++) { cResultStart.Items.Add(i + 1); } cResultStart.SelectedIndex = 0; if (confirmedSections.Count < 1) { InfoPopup popupNoResults = new InfoPopup("No results!"); popupNoResults.show(); return; } } if (e.UserState == null) return; //Only draw results when the view button is clicked tabBase.SelectedIndex = 2; for (int tabIter = (tabBase.Items.Count - 1); tabIter > 2; tabIter--) { tabBase.Items.RemoveAt(tabIter); } Tuple<int, int> range = (Tuple<int, int>)e.UserState; if (range.Item2 > confirmedSections.Count) range = new Tuple<int, int>(range.Item1, confirmedSections.Count); tabCount = range.Item1; List<List<ClassSection>> reportingList = new List<List<ClassSection>>(); lock (confirmedSections) { for (int x = range.Item1; x < range.Item2; x++) { List<ClassSection> classGroup = confirmedSections[x]; reportingList.Add(classGroup); } } if (reportingList.Count < 1) return; //If there are no elements, draw nothing. foreach (List<ClassSection> classGroup in reportingList) { //Make a grid and tab tabCount++; TabItem tab = new TabItem(); tab.Header = ""+tabCount; //The tab name Grid grid = new Grid(); //Draw horizontal lines for (int i = 0; i < 80; i++) { Line gridLines = new Line(); gridLines.X1 = 40; gridLines.X2 = tabBase.ActualWidth - 89; gridLines.Y1 = 60 + 6.7*i; gridLines.Y2 = 60 + 6.7*i; if (i % 3 == 0) gridLines.Stroke = new SolidColorBrush(Colors.DarkGray); else gridLines.Stroke = new SolidColorBrush(Colors.Transparent); gridLines.StrokeThickness = 0.5f; grid.Children.Add(gridLines); } //Draw vertical lines for (int i = 0; i < 6; i++) { Line gridLines = new Line(); gridLines.X1 = 40 + ((tabBase.ActualWidth / 6) + .80f) * i; gridLines.X2 = 40 + ((tabBase.ActualWidth / 6) + .80f) * i; gridLines.Y1 = 60; gridLines.Y2 = 583; gridLines.Stroke = new SolidColorBrush(Colors.DarkGray); gridLines.StrokeThickness = 0.5f; grid.Children.Add(gridLines); } //Draw each course on the grid tbaCount = 0; List<ClassSection> coursesInGroup = new List<ClassSection>(); foreach (ClassSection course in classGroup) { drawSchedule(grid, course.startTime, course.endTime, course.days, course.parentClass + "\n" + course.type, course.availability); coursesInGroup.Add(course); } tab.Content = grid; tabBase.Items.Add(tab); sectionsInGrid.Add(grid, coursesInGroup); } }