# HG changeset patch # User Nathan Phillip Brink # Date 2012-03-28 21:52:09 # Node ID 146ce01816f17f0296b641f1c17b5184b23f611d # Parent 1cf1f641a5e5e20f3cd0ee872b853242ce794804 Store the start and end dates of each section meeting. (Phase 1 in bug #122). diff --git a/inc/class.schedule.php b/inc/class.schedule.php --- a/inc/class.schedule.php +++ b/inc/class.schedule.php @@ -189,7 +189,7 @@ class Schedule * NULL on success, a string on error which is a message for the * user and a valid XHTML fragment. */ - function addSection($course_name, $letter, $time_start, $time_end, $days, $synonym = NULL, $instructor = NULL, $location = NULL, $type = 'lecture', $slot = 'default', $credit_hours = -1.0) + function addSection($course_name, $letter, $time_start, $time_end, $days, $synonym = NULL, $instructor = NULL, $location = NULL, $type = 'lecture', $slot = 'default', $credit_hours = -1.0, $date_start = NULL, $date_end = NULL) { if (empty($letter) && (empty($time_start) || !strcmp($time_start, 'none')) && (empty($time_end) || !strcmp($time_end, 'none')) && empty($days) && empty($synonym) && empty($instructor) && empty($location) && (empty($type) || !strcmp($type, 'lecture')) @@ -209,6 +209,15 @@ class Schedule return 'Invalid credit-hour specification of ' . htmlentities($credit_hours) . ' for ' . htmlentities($course_name) . '-' . htmlentities($letter) . '. Please use a floating point number or do not enter anything if the number of credit hours is not known.'; } + if (empty($date_start) != empty($date_end) + || !empty($date_start) && !is_numeric($date_start) + || !empty($date_end) && !is_numeric($date_end)) + { + return 'Invalid date range specification of ' . htmlentities($date_start, ENT_QUOTES) + . ' through ' . htmlentities($date_end, ENT_QUOTES) + . '. Was expecting two valid unix timestamps or two empty values.'; + } + foreach ($this->courses as $course) if (!strcmp($course_name, $course->getName())) { @@ -218,7 +227,7 @@ class Schedule $section = new Section($letter, array(), $synonym, $credit_hours); $course->section_add($section, $slot); } - $section->meeting_add(new SectionMeeting($days, $time_start, $time_end, $location, $type, $instructor)); + $section->meeting_add(new SectionMeeting($days, $time_start, $time_end, $location, $type, $instructor, $date_start, $date_end)); return; } diff --git a/inc/class.section.php b/inc/class.section.php --- a/inc/class.section.php +++ b/inc/class.section.php @@ -23,8 +23,10 @@ require_once dirname(__FILE__) . DIRECTO /** * \brief * Represent a Section associated with a Course. + * + * Iterating over a Section yields section_SectionMeeting objects. */ -class Section +class Section implements IteratorAggregate { private $letter; // Section letter @@ -70,6 +72,15 @@ class Section $this->credit_hours = (float)$credit_hours; } + /** + * \brief + * Implements the IteratorAggregate interface. + */ + public function getIterator() + { + return new ArrayIterator($this->meetings); + } + public function getLetter() { return $this->letter; diff --git a/inc/class.section_meeting.inc b/inc/class.section_meeting.inc --- a/inc/class.section_meeting.inc +++ b/inc/class.section_meeting.inc @@ -35,7 +35,9 @@ */ class SectionMeeting { + private $date_start; private $time_start; + private $date_end; private $time_end; private $days; private $location; @@ -64,12 +66,21 @@ class SectionMeeting * school's notation. * \param $instructor * The instructor for this section meeting. + * \param $date_start + * A timestamp marking some time prior to the first occurence of + * the section_meeting. + * \param $date_end + * A timestamp marking some time after the end of the last + * occurence of this section_meeting. */ - public function __construct($days, $time_start, $time_end, $location = NULL, $type = 'lecture', $instructor = NULL) + public function __construct($days, $time_start, $time_end, $location = NULL, $type = 'lecture', $instructor = NULL, $date_start = NULL, $date_end = NULL) { $this->days_set($days); + + $this->date_start = empty($date_start) ? NULL : (int)$date_start; $this->time_start = $time_start; + $this->date_end = empty($date_end) ? NULL : (int)$date_end; $this->time_end = $time_end; $this->location = $location; @@ -197,6 +208,26 @@ class SectionMeeting /** * \brief + * Return the unix timestamp of a time prior to the first section + * meeting or NULL if unknown. + */ + public function date_start_get() + { + return empty($this->date_start) ? NULL : $this->date_start; + } + + /** + * \brief + * Return the unix timestamp of a time after the last section + * meeting or NULL if unknown. + */ + public function date_end_get() + { + return empty($this->date_end) ? NULL : $this->date_end; + } + + /** + * \brief * Check if this section conflicts with the given section. * * \param $that @@ -249,7 +280,9 @@ class SectionMeeting static $daymap = array(0 => 'm', 1 => 't', 2 => 'w', 3 => 'h', 4 => 'f', 5 => 's', 6 => 'u'); $json_array = array( - 'time_start' => $this->time_start, + 'date_start' => empty($this->date_start) ? NULL : $this->date_start, + 'time_start' => $this->time_start, + 'date_end' => empty($this->date_end) ? NULL : $this->date_end, 'time_end' => $this->time_end, 'days' => array(), 'location' => $this->location, @@ -274,10 +307,13 @@ class SectionMeeting */ public static function from_json_array(array $json_array) { + $json_array += array('date_start' => NULL, 'date_end' => NULL); $days = ''; foreach ($json_array['days'] as $day => $meets) if ($meets) $days .= $day; - return new SectionMeeting($days, $json_array['time_start'], $json_array['time_end'], $json_array['location'], $json_array['type'], $json_array['instructor']); + return new SectionMeeting($days, $json_array['time_start'], $json_array['time_end'], + $json_array['location'], $json_array['type'], $json_array['instructor'], + $json_array['date_start'], $json_array['date_end']); } } diff --git a/inc/class.semester.inc b/inc/class.semester.inc --- a/inc/class.semester.inc +++ b/inc/class.semester.inc @@ -95,6 +95,11 @@ class Semester if (!isset($class_parts['course'])) throw new ErrorException('I was given a class with an invalid name: `' . $class->getName() . '\''); + foreach ($class as $course_slot) + foreach ($course_slot as $section) + foreach ($section as $meeting) + $this->time_set_section_meeting($meeting); + if (!isset($this->departments[$class_parts['department']])) $this->departments[$class_parts['department']] = array(); $department =& $this->departments[$class_parts['department']]; @@ -221,6 +226,9 @@ class Semester */ public function section_add($dept, $class, Section $section, $title = NULL, $course_slot_id = 'default') { + foreach ($section as $meeting) + $this->time_set_section_meeting($meeting); + $dept = strtoupper($dept); $class = strtoupper($class); @@ -270,6 +278,8 @@ class Semester */ public function section_meeting_add($dept, $course, $title, $section, $synonym, $section_meeting, $course_slot_id = 'default', $credit_hours = -1.0) { + $this->time_set_section_meeting($section_meeting); + $dept = strtoupper($dept); $course = strtoupper($course); @@ -402,6 +412,23 @@ class Semester /** * \brief + * Consider a section_meeting's start and end dates and make + * appropriate time_start_set_test() and time_end_set_test() + * calls. + */ + public function time_set_section_meeting(SectionMeeting $meeting) + { + $date_start = $meeting->date_start_get(); + if (!empty($date_start)) + $this->time_start_set_test($date_start); + + $date_end = $meeting->date_end_get(); + if (!empty($date_end)) + $this->time_end_set_test($date_end); + } + + /** + * \brief * Get a semester's year. */ public function year_get() diff --git a/input.php b/input.php --- a/input.php +++ b/input.php @@ -154,7 +154,9 @@ elseif ($errors_fix) . json_encode($section['location']) . ', ' . json_encode($section['type']) . ', ' . json_encode($section['slot']) . ', ' - . json_encode(isset($section['credit_hours']) ? $section['credit_hours'] : -1) . ');' . PHP_EOL; + . json_encode(isset($section['credit_hours']) ? $section['credit_hours'] : -1) . ', ' + . json_encode(empty($section['date_start']) ? NULL : $section['date_start']) . ', ' + . json_encode(empty($section['date_end']) ? NULL : $section['date_end']) . ');' . PHP_EOL; $my_hc .= PHP_EOL; } } diff --git a/process.php b/process.php --- a/process.php +++ b/process.php @@ -218,10 +218,13 @@ if(!$DEBUG) /* Skip the section name, which isn't a section */ if(is_array($section)) { - if (empty($section['slot'])) - $section['slot'] = 'default'; + $section += array( + 'slot' => 'default', + 'date_start' => NULL, + 'date_end' => NULL, + ); - $error_string = $allClasses->addSection($course['name'], $section['letter'], $section['start'], $section['end'], arrayToDays(empty($section['days']) ? array() : $section['days'], 'alpha'), $section['synonym'], $section['professor'], $section['location'], $section['type'], $section['slot'], $section['credit_hours']); + $error_string = $allClasses->addSection($course['name'], $section['letter'], $section['start'], $section['end'], arrayToDays(empty($section['days']) ? array() : $section['days'], 'alpha'), $section['synonym'], $section['professor'], $section['location'], $section['type'], $section['slot'], $section['credit_hours'], $section['date_start'], $section['date_end']); if ($error_string !== NULL) $errors[] = $error_string; } diff --git a/school.d/calvin.crawl.inc b/school.d/calvin.crawl.inc --- a/school.d/calvin.crawl.inc +++ b/school.d/calvin.crawl.inc @@ -384,27 +384,21 @@ function calvin_crawl_semester(array $sc foreach (array('date_start', 'date_end', 'meeting_type', 'days', 'time_start', 'time_end', 'meeting_place', 'meeting_type') as $var) school_crawl_logf($school_crawl_log, 10, "%s:%s", $var, ${$var}); - $semester->section_meeting_add($section_id['department'], $section_id['course'], $title, $section_id['section'], $synonym, - new SectionMeeting($days, $time_start, $time_end, $meeting_place, $meeting_type, $faculty_name), 'default', $credits); - - /* - * Try to update semester's longetivity stats to help the - * school_semester_guess() function: - */ $date_start_time = strptime($date_start, '%m/%d/%Y'); $date_end_time = strptime($date_end, '%m/%d/%Y'); + if ($date_start_time !== FALSE) + $date_start_time = school_crawl_gmmktime($date_start_time, -5 * 60*60); + else + $date_start_time = NULL; + if ($date_end_time !== FALSE) + $date_end_time = school_crawl_gmmktime($date_end_time, -5 * 60*60) + 24*60*60; + else + $date_end_time = NULL; - if ($date_start_time !== FALSE) - { - $date_start_time = school_crawl_gmmktime($date_start_time, -5 * 60*60); - $semester->time_start_pool_add($date_start_time); + $semester->section_meeting_add($section_id['department'], $section_id['course'], $title, $section_id['section'], $synonym, + new SectionMeeting($days, $time_start, $time_end, $meeting_place, $meeting_type, $faculty_name, $date_start_time, $date_end_time), 'default', $credits); + } - if ($date_end_time !== FALSE) - { - $date_end_time = school_crawl_gmmktime($date_end_time, -5 * 60*60); - $semester->time_end_pool_add($date_end_time); - } - } } if (!preg_match(';Page ([0-9]+) of ([0-9]+)\$;m', $html, $pages)) diff --git a/school.d/ccbcmd.crawl.inc b/school.d/ccbcmd.crawl.inc --- a/school.d/ccbcmd.crawl.inc +++ b/school.d/ccbcmd.crawl.inc @@ -292,18 +292,18 @@ function ccbcmd_crawl_semester($school, $days = school_crawl_days_str_format($school_crawl_log, $children->item($section_offsets['days'])->textContent); + $section_dates = $children->item($section_offsets['dates'])->textContent; + $date_start = $date_end = NULL; + if (preg_match(';^([0-9]+)/([0-9]+)-([0-9]+)/([0-9]+)$;', $section_dates, $section_dates_matches)) + { + $date_start = gmmktime(0, 0, 0, $section_dates_matches[1], $section_dates_matches[2], $semester->year_get()); + $date_end = gmmktime(0, 0, 0, $section_dates_matches[3], $section_dates_matches[4], $semester->year_get()); + } + $section->meeting_add(new SectionMeeting($days, school_crawl_time_format($time_start), school_crawl_time_format($time_end), $children->item($section_offsets['location'])->textContent, 'lecture', - $instructor)); - - /* check if a semester's date range should be increased */ - $section_dates = $children->item($section_offsets['dates'])->textContent; - if (preg_match(';^([0-9]+)/([0-9]+)-([0-9]+)/([0-9]+)$;', $section_dates, $section_dates_matches)) - { - $semester->time_start_set_test(gmmktime(0, 0, 0, $section_dates_matches[1], $section_dates_matches[2], $semester->year_get())); - $semester->time_end_set_test(gmmktime(0, 0, 0, $section_dates_matches[3], $section_dates_matches[4], $semester->year_get())); - } + $instructor, $date_start, $date_end)); } } diff --git a/school.d/cedarville.crawl.inc b/school.d/cedarville.crawl.inc --- a/school.d/cedarville.crawl.inc +++ b/school.d/cedarville.crawl.inc @@ -291,15 +291,11 @@ function cedarville_crawl_semester(array $type = school_crawl_meeting_type($meeting_matches[1]); /* check for daterange information -- i.e., if the first regex successfully matched: */ + $date_start = $date_end = NULL; if (count($meeting_matches) > 7) { $date_start = school_crawl_gmmktime(strptime($meeting_matches[6], '%m/%d/%y'), CEDARVILLE_TIMEZONE_OFFSET); $date_end = school_crawl_gmmktime(strptime($meeting_matches[7], '%m/%d/%y'), CEDARVILLE_TIMEZONE_OFFSET); - if (!empty($date_start) && !empty($date_end)) - { - $semester->time_start_set_test($date_start); - $semester->time_end_set_test($date_end); - } } /* @@ -312,7 +308,8 @@ function cedarville_crawl_semester(array $instructors[$meeting_i] = $instructors[0]; $meetings[] = new SectionMeeting($days, $time_start, $time_end, - $room, $type, $instructors[$meeting_i]); + $room, $type, $instructors[$meeting_i], + $date_start, $date_end); $meeting_i ++; } diff --git a/school.d/hope.crawl.inc b/school.d/hope.crawl.inc --- a/school.d/hope.crawl.inc +++ b/school.d/hope.crawl.inc @@ -278,6 +278,7 @@ function hope_crawl_semester(array $scho continue; } + $date_start = $date_end = NULL; if (preg_match(',(\\d\\d)/(\\d\\d)-(\\d\\d)/(\\d\\d),', $section_csv[$fields['Date']], $matches)) { list(, $m_start, $d_start, $m_end, $d_end) = $matches; @@ -286,8 +287,8 @@ function hope_crawl_semester(array $scho $y_start = $y_end = $semester->year_get(); if ($m_end < $m_start) $y_end ++; - $semester->time_start_set_test(gmmktime(0, 0, 0, $m_start, $d_start, $y_start)); - $semester->time_end_set_test(gmmktime(0, 0, 0, $m_end, $d_end, $y_end)); + $date_start = gmmktime(0, 0, 0, $m_start, $d_start, $y_start); + $date_end = gmmktime(0, 0, 0, $m_end, $d_end, $y_end); } } @@ -314,7 +315,8 @@ function hope_crawl_semester(array $scho $section_meeting = new SectionMeeting($days, $time_start, $time_end, $location, $type, - $instructor); + $instructor, + $date_start, $date_end); $semester->section_meeting_add($subject_id, $course_id, $title, diff --git a/school.d/umich.crawl.inc b/school.d/umich.crawl.inc --- a/school.d/umich.crawl.inc +++ b/school.d/umich.crawl.inc @@ -274,32 +274,31 @@ function umich_crawl_semester(array $sch if (strlen($curr_value = trim($row[$fields[$key]]))) $row_accumulation[$key] = $curr_value; - $semester->section_meeting_add($dept, $course_id, trim($row[$fields['Course Title']]), - trim($row[$fields['Section']]), $synonym, - new SectionMeeting($days, $time_start, $time_end, - trim($row[$fields['Location']]), - $meeting_type, - $row_accumulation['Instructor']), - $meeting_type, - $credit_hours); - /* - * If the section so far passed as being a normal section, use - * its start and end dates to help determine the semester's - * respective start and end dates. + * Grab start/stop dates. */ + $date_start = $date_end = NULL; $date_start_tm = strptime(trim($row[$fields['Start Date']]), '%m/%d/%Y'); $date_end_tm = strptime(trim($row[$fields['End Date']]), '%m/%d/%Y'); if (!empty($date_start_tm) && !empty($date_end_tm)) { $date_start = school_crawl_gmmktime($date_start_tm); $date_end = school_crawl_gmmktime($date_end_tm); - if ($date_start > 1000000 && $date_end > 1000000) + if ($date_start < 1000000 || $date_end < 1000000) { - $semester->time_start_set_test($date_start); - $semester->time_end_set_test($date_end); + $date_start = $date_end = NULL; } } + + $semester->section_meeting_add($dept, $course_id, trim($row[$fields['Course Title']]), + trim($row[$fields['Section']]), $synonym, + new SectionMeeting($days, $time_start, $time_end, + trim($row[$fields['Location']]), + $meeting_type, + $row_accumulation['Instructor'], + $date_start, $date_end), + $meeting_type, + $credit_hours); } } diff --git a/scripts/scheduleInput.js b/scripts/scheduleInput.js --- a/scripts/scheduleInput.js +++ b/scripts/scheduleInput.js @@ -17,9 +17,12 @@ * along with SlatePermutate. If not, see . */ - //-------------------------------------------------- - // General Notes - //-------------------------------------------------- +/** + * \file + * + * If you are reading this file, you may be interested in contributing + * to slate_permutate. Please see http://ohnopub.net/w/SlatePermutate . + */ /** * \brief @@ -127,7 +130,7 @@ function addTips() * \brief * Add a section to a class. */ -function add_section_n(cnum, name, synonym, stime, etime, days, instructor, location, type, slot, credit_hours) +function add_section_n(cnum, name, synonym, stime, etime, days, instructor, location, type, slot, credit_hours, date_start, date_end) { var snum = last_section_i ++; var cssclasses = 'section class' + cnum + ' ' + safe_css_class('slot-' + slot); @@ -212,6 +215,8 @@ function add_section_n(cnum, name, synon '' + '' + '' + + '' + + '' + ''; /* @@ -244,6 +249,8 @@ function add_section_n(cnum, name, synon section_tr.find('.section-location-entry').val(location); section_tr.find('.section-type-entry').val(type); section_tr.find('.section-credit-hours-entry').val(credit_hours); + section_tr.find('.section-date-start-entry').val(date_start); + section_tr.find('.section-date-end-entry').val(date_end); /* unhide the saturday and sunday columns if they're used by autocomplete data */ if (days.u) @@ -257,7 +264,7 @@ function add_section_n(cnum, name, synon } function add_section(cnum) { - var section_i = add_section_n(cnum, '', '', '', '', {}, '', '', '', 'default', -1); + var section_i = add_section_n(cnum, '', '', '', '', {}, '', '', '', 'default', -1, null, null); if (cnum == slate_permutate_course_free) course_free_check(cnum); return section_i; @@ -292,8 +299,15 @@ function add_sections(cnum, data) section.slot = 'default'; if (section.credit_hours === undefined) section.credit_hours = -1; + if (section.date_start === undefined) + { + section.date_start = null; + section.date_end = null; + } - add_section_n(cnum, section.section, section.synonym, section.time_start, section.time_end, section.days, section.instructor, section.location, section.type, section.slot, section.credit_hours); + add_section_n(cnum, section.section, section.synonym, section.time_start, section.time_end, + section.days, section.instructor, section.location, section.type, section.slot, + section.credit_hours, section.date_start, section.date_end); }); /*