. */ $incdir = dirname(__FILE__) . DIRECTORY_SEPARATOR; include_once $incdir . 'class.course.inc'; include_once $incdir . 'class.section.php'; include_once $incdir . 'class.page.php'; require_once $incdir . 'school.inc'; require_once $incdir . 'math.inc'; /* * Load a Classes -> Course converter class for the sake of the * Schedule::__wakeup() magic function. */ require_once $incdir . 'class.classes_convert.inc'; /** * \brief * Finds possible Section combinations for a user's given Courses * and stores and displays the results. * * Represents a schedule of a week. Stores the classes that are part * of that week and calculates all the possible permutations. */ class Schedule { /* * Variables for upgrading from saved schedules created when there * was a class called Classes. */ private $classStorage; // array of courses private $nclasses; // Integer number of classes /** * \brief * Provides a mapping to regain the user's original input. * * Currently, the Schedule object cannot natively handle CourseSlot * objects properly. It assumes that each Course has one and only * one CourseSlot. This array maps each Course object stored in * $classStorage onto the index of the course it was originally * from. I.e., if the Course at index 0 had two CourseSlot objects, * array(0 => 0, 1 => 0, 2 => 1) would map these two CourseSlot * objects onto the same Course object and have the next CourseSlot * be mapped into a separate Course object. */ private $course_slot_mappings; /* My member variables. */ private $courses; private $nPermutations = 0; // Integer number of real permutations private $possiblePermutations; // Integer number of possible permutations private $scheduleName; // String name of schedule private $storage; // Integer array of valid schedules /** * \brief * The school_id of the school this schedule was created for. */ private $school_id; /** * \brief * The semester this schedule was created for. * * The semester array is stored in full in a schedule because some * schools do not keep a backlog of all semesters for their course * data. Such a school is calvin. We want to be able to access, for * example, the friendly name and so on of a semester even one year * after the semester is created without worrying about having that * semester be stored in the autocomplete cache. */ private $semester; /* The
' . PHP_EOL . ' Edit' . PHP_EOL . ' Print' . PHP_EOL . ' ' . PHP_EOL; if (!empty($parent_schedule)) { echo ' Parent' . PHP_EOL; } echo ' Home' . PHP_EOL . '
'. PHP_EOL . 'Having problems? Let us know.
' . PHP_EOL . 'Keyboard Shortcut: Left and right arrow keys switch between schedules
' . PHP_EOL; } echo "\n"; if($this->nPermutations > 0) { /* * Figure out if we have to deal with Saturday and then deal * with it. * * Also, ensure that our $time array is big enough for all of * these courses. */ $max_day_plusone = 5; $have_saturday = FALSE; $max_time = (int)max($time); $min_time = (int)min($time); $sort_time = FALSE; foreach ($this->courses as $course) foreach ($course as $course_slot) { for ($si = 0; $si < $course_slot->sections_count(); $si ++) foreach ($course_slot->section_get_i($si)->getMeetings() as $meeting) { /* Saturdayness */ if ($meeting->getDay(5)) { $max_day_plusone = 6; $have_saturday = TRUE; } /* very late / very early classes */ while ((int)ltrim($meeting->getEndTime(), '0') > $max_time) { $max_time += $max_time + 30; while ($max_time % 100 >= 60) $max_time += 40; /* + 100 - 60 */ $time[] = $max_time; } while ((int)ltrim($meeting->getStartTime(), '0') < $min_time) { $max_time += 30; while ($min_time % 100 < 30) $min_time -= 40; /* + 60 - 100 */ $min_time -= 30; $time[] = $min_time; $sort_time = TRUE; } } } /* ensure that early times are actually first ;-) */ if ($sort_time) sort($time); echo '' . PHP_EOL . ' ' . PHP_EOL . ' Note: The registration information above corresponds to the sections' . PHP_EOL . ' displayed on the currently selected tab.' . PHP_EOL . ' ' . PHP_EOL . '
' . PHP_EOL . '' . PHP_EOL . ' ' . PHP_EOL . ' Disclaimer: You are responsible for' . PHP_EOL . ' double-checking the information you get from and input into slate_permutate' . PHP_EOL . ' when registering for classes. There is no guarantee that the harvested' . PHP_EOL . ' information is correct or that slate_permutate will handle' . PHP_EOL . ' the information you enter correctly.' . PHP_EOL . ' ' . PHP_EOL . '
' . PHP_EOL . '| ' . ($i + 1) . " | \n" . "Monday | \n" . "Tuesday | \n" . "Wednesday | \n" . "Thursday | \n" . "Friday | \n"; if ($have_saturday) echo "Saturday | \n"; echo "
| " . $this->prettyTime($time[$r]) . " | \n"; /* currently, 0-5 = monday-saturday */ for($dayLoop = 0; $dayLoop < $max_day_plusone; $dayLoop++) { /* Makes sure there is not a class already in progress */ if($rowspan[$dayLoop] <= 0) { for($j = 0; $j < count($this->courses); $j++) { $course = $this->courses[$j]; foreach ($course as $course_slot) { $section_index = $this->storage[$i][$j]; $section = $course_slot->section_get_i($section_index); /* iterate through all of a class's meeting times */ $meetings = $section->getMeetings(); /* find any meeting which are going on at this time */ $current_meeting = NULL; foreach ($meetings as $meeting) { if ($meeting->getDay($dayLoop) && $meeting->getStartTime() >= $time[$r] && $meeting->getStartTime() < $time[$r+1]) { $current_meeting = $meeting; } } if ($current_meeting) { /* calculate how many rows this section should span */ for ($my_r = $r; $my_r < (count($time)-1) && $current_meeting->getEndTime() > $time[$my_r]; $my_r ++) ; $rowspan[$dayLoop] = $my_r - $r; $single_multi = 'single'; if ($rowspan[$dayLoop] > 1) $single_multi = 'multi'; $title = $course->title_get(); if (empty($title)) $title = ''; else $title .= ' '; $carret = ' ' . htmlentities("' . '' . htmlentities($title) . '' . PHP_EOL . htmlentities($course->getName(), ENT_QUOTES) . '-' . htmlentities($section->getLetter(), ENT_QUOTES) . "\n" . '' . htmlentities($current_meeting->instructor_get(), ENT_QUOTES) . "\n" . '' . htmlentities($current_meeting->getLocation(), ENT_QUOTES) . "\n" . '' . htmlentities($section->getSynonym(), ENT_QUOTES) . "\n" . '' . htmlentities($section_credit_hours, ENT_QUOTES) . ' Credits' . PHP_EOL . " | \n"; /* for the ``Registration Codes'' dialogue: */ if (empty($permutations_courses[$j])) { $singleton_course = new Course($course->getName(), $course->title_get()); $singleton_course->section_add($section, $course_slot->id_get()); $permutation_courses[$j] = $singleton_course->to_json_array(); } $filled = TRUE; } } /* $course_slot */ } } if ($rowspan[$dayLoop] > 0) { $filled = TRUE; $rowspan[$dayLoop] --; } /* If the cell was not filled, fill it with an empty cell. */ if(!$filled) { echo "\n"; } $filled = FALSE; } // End of row echo " | 
Credit Hours: ' . sum($credit_hours) . '
' . PHP_EOL; echo '' . ' '. htmlentities(json_encode($permutation_courses)) . "\n" . 'There are no possible schedules. Please try again.
'; } echo '' . PHP_EOL; if ($this->possiblePermutations == 1) echo 'There was one possible permutation.'; else echo 'There were a total of ' . $this->possiblePermutations . ' possible permutations.'; if ($this->possiblePermutations == $this->nPermutations) echo ' No permutations had'; elseif (!$this->nPermutations) echo ' All permutations had'; else echo ' Only ' . $this->nPermutations . ' permutation' . ($this->nPermutations == 1 ? '' : 's') . ' had no'; echo ' scheduling conflicts.' . PHP_EOL . '
' . PHP_EOL; if ($this->created) echo '' . '' . PHP_EOL . ' Created ' . gmdate('c', $this->created) . '.' . PHP_EOL . '
' . PHP_EOL; $outputPage->foot(); } //-------------------------------------------------- // Changes the title of the page. //-------------------------------------------------- function changeTitle($t) { $this->title = $t; } //-------------------------------------------------- // Make the time "pretty" //-------------------------------------------------- function prettyTime($t){ if($t >= 1200) { if ($t > 1259) $t = ($t - 1200); return substr($t, 0, strlen($t)-2) . ":" . substr($t, strlen($t)-2, strlen($t)) . " PM"; } else { return substr($t, 0, strlen($t)-2) . ":" . substr($t, strlen($t)-2, strlen($t)) . " AM"; } } /** * \brief * fetch the number of classes */ function nclasses_get() { return count($this->courses); } /** * \brief * Fetch a specified class by its key. * * Use Schedule::courses_get() instead of this function if the code * you're writing understand CourseSlot objects. * * \see Schedule::courses_get(). */ public function class_get($class_key) { return $this->courses[$class_key]; } /** * \brief * Get an array of Course objects as originally inputted by the * user. */ public function courses_get() { /* * As Mr. Westra would say, just map them courses back into their * original forms. */ $courses = array(); foreach ($this->courses as $course_i => $course) { $mapping = $this->course_slot_mappings[$course_i]; if (empty($courses[$mapping])) $courses[$mapping] = new Course($course->getName(), $course->title_get()); foreach ($course as $course_slot) $courses[$mapping]->course_slot_add($course_slot); } return $courses; } /** * \brief * Set my global ID. * * Only to be called by schedule_store_store(). */ function id_set($id) { $this->id = $id; } /* * \brief * Get my global ID. */ function id_get() { return $this->id; } /** * \brief * Write out a relative URL for a particular schedule. * * Takes into account the $clean_urls setting. * * \param $id * The ID of the schedule to link to. * \param $page * The page/tab of the schedule to link to. Defaults to 0. * \return * A string, the URL used to access the specified * schedule. Remember that if this string is inserted into an * XHTML document, htmlentities() must be called on it. */ public static function url($id, $page = 0) { global $clean_urls; $query = array(); if ($clean_urls) $url = (int)$id; else { $url = 'process.php'; $query['s'] = (int)$id; } if ($page) $query['page'] = (int)$page; if (!empty($query)) { $query_processed = array(); foreach ($query as $key => $value) $query_processed[] = $key . '=' . rawurlencode($value); $url .= '?' . implode('&', $query_processed); } return $url; } /** * \brief * Return the URL used to access this schedule. * * Convenience wrapper around Schedule::url(). * * \param $page * Which page (tab) of the schedule to link to. * \return * A raw URL (one that must be htmlentities()ized before putting * into HTML). */ public function my_url($page = 0) { return Schedule::url($this->id, $page); } /** * \brief * Get the ID of the schedule from which this schedule was * derived. */ public function parent_get() { return $this->parent_id; } /** * \brief * Get the unix timestamp of when this schedule was created * (saved). * * \return * A unix timestamp. 0 if the timestamp is unavailable. */ public function created_get() { return $this->created; } /** * \brief * A magic function which tries to upgrade old serialized sections * to the new format. */ function __wakeup() { if ($this->nclasses != -1) { /* this Schedule needs to be upgraded from Classes to Course */ $this->courses = array(); foreach ($this->classStorage as $classes) $this->courses[] = $classes->to_course(); $this->nclasses = -1; } if (empty($this->parent_id)) $this->parent_id = NULL; if (empty($this->school_id)) { /* Ensure we have $_SESSION. */ page::session_start(); $school = school_load_guess(FALSE); $this->school_id = $school['id']; } if (empty($this->semester)) { if (empty($school)) { /* Ensure we have $_SESSION. */ page::session_start(); $school = school_load($this->school_id); $this->semester = school_semester_guess($school); } } if (empty($this->course_slot_mappings)) { $this->course_slot_mappings = array(); foreach ($this->courses as $course_i => $course) $this->course_slot_mappings[$course_i] = count($this->course_slot_mappings); } if (empty($this->created)) $this->created = 0; } }