@@ -535,30 +535,30 @@ class Schedule
* 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;
$dayloop_max = 5;
$have_sunday = FALSE;
$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 */
/* Sundayness and Saturdayness */
if ($meeting->getDay(6))
$have_sunday = TRUE;
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)
@@ -577,12 +577,15 @@ class Schedule
/* ensure that early times are actually first ;-) */
if ($sort_time)
sort($time);
if ($have_saturday)
$dayloop_max = 6;
echo ' <div id="regDialog" title="Registration Codes">' . PHP_EOL
. ' <div id="regDialog-content"></div>' . PHP_EOL
. ' <p class="regDialog-disclaimer graytext">' . PHP_EOL
. ' <em>' . PHP_EOL
. ' Note: The registration information above corresponds to the sections' . PHP_EOL
. ' displayed on the currently selected tab.' . PHP_EOL
@@ -676,33 +679,42 @@ class Schedule
// Beginning of table
echo " <table style=\"empty-cells:show;\" border=\"1\" cellspacing=\"0\">\n";
// Header row
echo " <tr>\n"
. ' <td class="none permuteNum">' . ($i + 1) . "</td>\n"
. " <td class=\"day\">Monday</td>\n"
. ' <td class="none permuteNum">' . ($i + 1) . "</td>\n";
if ($have_sunday)
echo ' <td class="day">Sunday</td>' . PHP_EOL;
echo " <td class=\"day\">Monday</td>\n"
. " <td class=\"day\">Tuesday</td>\n"
. " <td class=\"day\">Wednesday</td>\n"
. " <td class=\"day\">Thursday</td>\n"
. " <td class=\"day\">Friday</td>\n";
echo " <td class=\"day\">Saturday</td>\n";
echo " </tr>\n";
$last_meeting = array();
$rowspan = array(0, 0, 0, 0, 0, 0);
$rowspan = array(0, 0, 0, 0, 0, 0, 0);
for($r = 0; $r < (count($time)-1); $r++)
. " <td class=\"time\">" . $this->prettyTime($time[$r]) . "</td>\n";
/* currently, 0-5 = monday-saturday */
for($dayLoop = 0; $dayLoop < $max_day_plusone; $dayLoop++)
/*
* Currently, 6, 0-5 = sunday, monday-saturday. We use
* the trick that -1 through 5 mod 7 is
* sunday-saturday.
for($dayLoop = $have_sunday ? -1 : 0; $dayLoop < $dayloop_max; $dayLoop = ($dayLoop + 1) % 7)
if ($dayLoop < 0)
$dayLoop = 6;
/* 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];
@@ -43,15 +43,16 @@ class SectionMeeting
/**
* \brief
* Construct a SectionMeeting.
* \param $days
* A string of single-char day upon which a section meets. Monday
* is represented with 'm', Tuesday with 't', Wednesday with 'w',
* Thursday with 'h', and Friday with 'f'.
* A string of single-char day upon which a section meets. Sunday
* is represented with 'u', Monday with 'm', Tuesday with 't',
* Wednesday with 'w', Thursday with 'h', Friday with 'f', and
* Saturday with 's'.
* \param $time_start
* The time of day when the section meeting starts. Use
* school_crawl_time_format() or ensure that the time is formatted
* in 24-hour, 0-padded, 4-digit form (HHMM).
* \param $time_end
* The time of day when the section meeting ends.
@@ -80,17 +81,18 @@ class SectionMeeting
* Take a days of week string and store it into our $days of week array.
* \param $days_str
* The days of the week in a string format. One char per
* day. Mon-Sat is represented with 'm', 't', 'w', 'h', 'f', 's'.
* day. Sun-Sat is represented with 'u', 'm', 't', 'w', 'h', 'f',
* 's'.
private function days_set($days_str)
$this->days = array(0 => FALSE, 1 => FALSE, 2 => FALSE, 3 => FALSE, 4 => FALSE, 5 => FALSE);
$this->days = array(0 => FALSE, 1 => FALSE, 2 => FALSE, 3 => FALSE, 4 => FALSE, 5 => FALSE, 6 => FALSE);
$days_str_strlen = strlen($days_str);
for ($i = 0; $i < $days_str_strlen; $i ++)
$this->days[self::day_atoi($days_str[$i])] = TRUE;
@@ -99,15 +101,17 @@ class SectionMeeting
* Convert a day letter to a day numeral.
* Works fine if you give the numeral as well.
private static function day_atoi($day_c)
static $day_atoi = array('m' => 0, 't' => 1, 'w' => 2, 'h' => 3, 'f' => 4, 's' => 5,
'M' => 0, 'T' => 1, 'W' => 2, 'H' => 3, 'F' => 4, 'S' => 5,
0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5);
static $day_atoi = array(
'm' => 0, 't' => 1, 'w' => 2, 'h' => 3, 'f' => 4, 's' => 5, 'u' => 6,
'M' => 0, 'T' => 1, 'W' => 2, 'H' => 3, 'F' => 4, 'S' => 5, 'U' => 6,
0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,
);
return $day_atoi[$day_c];
@@ -215,13 +219,13 @@ class SectionMeeting
* Now we know that the sections meetings overlap in start/end
* times. But if they don't both meet on the same day at least
* once, they don't conflict.
for ($day = 0; $day < 6; $day ++)
for ($day = 0; $day < 7; $day ++)
if ($this->getDay($day) && $that->getDay($day))
return TRUE;
@@ -239,24 +243,24 @@ class SectionMeeting
* have multiple meeting times. Thus, we simulate this by having
* multiple instances of the same section but just with different
* times in the UI.
public function to_json_array()
static $daymap = array(0 => 'm', 1 => 't', 2 => 'w', 3 => 'h', 4 => 'f', 5 => 's');
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,
'time_end' => $this->time_end,
'days' => array(),
'location' => $this->location,
'instructor' => $this->instructor,
'type' => $this->type,
$json_array['days'][$daymap[$day]] = $this->getDay($day);
return $json_array;
@@ -162,20 +162,20 @@ function school_crawl_gmmktime(array $tm
* An array of day names. These may be common abbreviations or
* truncations (any truncations must be two chars long for
* simplicity. One-char representations are supported, however, but
* use 'm', 't', 'w', 'h', 'f' to distinguish Thursday and
* Tuesday. 'r' may also be used for Thursday.). Case does not
* matter. 's' is for Saturday, based on CCBCMD.
* matter. 's' is for Saturday, based on CCBCMD. 'u' is for Sunday.
* \return
* slate_permutate's strange internal days representation.
function school_crawl_days_format(array $school_crawl_log, $days)
static $daymap_1 = array('m' => 'm', 't' => 't', 'w' => 'w', 'h' => 'h', 'r' => 'h', 'f' => 'f', 's' => 's');
static $daymap_2 = array('th' => 'h');
static $daymap_1 = array('u' => 'u', 'm' => 'm', 't' => 't', 'w' => 'w', 'h' => 'h', 'r' => 'h', 'f' => 'f', 's' => 's');
static $daymap_2 = array('su' => 'u', 'th' => 'h');
$my_days = array();
foreach ($days as $day)
$day_orig = $day;
$day = strtolower(substr(trim($day), 0, 2));
@@ -310,12 +310,13 @@ if (!empty($_REQUEST['selectsemester']))
<colgroup>
<col />
<col class="sunday<?php if (school_has_auto($inputPage->get_school())) echo ' collapsed';?>" />
<col class="saturday<?php if (school_has_auto($inputPage->get_school())) echo ' collapsed';?>" />
@@ -326,18 +327,19 @@ if (!empty($_REQUEST['selectsemester']))
<tr>
<td>Class ID</td>
<td class="center" id="letterNumber">Section</td>
<td class="center">Prof</td>
<td class="center">Start Time</td>
<td class="center">End Time</td>
<td class="center">Su</td>
<td class="center">M</td>
<td class="center">Tu</td>
<td class="center">W</td>
<td class="center">Th</td>
<td class="center">F</td>
<td class="center">S</td>
<td class="center">Sa</td>
<td class="center"></td>
</tr>
</table>
</td>
@@ -378,13 +380,14 @@ function input_course_js(Course $course,
foreach ($meetings as $meeting)
$js .= $whitespace . 'add_section_n(class_last, ' . json_encode($section->getLetter()) . ', '
. json_encode($section->getSynonym()) . ', '
. json_encode($meeting->getStartTime()) . ', '
. json_encode($meeting->getEndTime()) . ', '
. json_encode(array('m' => $meeting->getDay(0), 't' => $meeting->getDay(1), 'w' => $meeting->getDay(2), 'h' => $meeting->getDay(3), 'f' => $meeting->getDay(4),
. json_encode(array('u' => $meeting->getDay(6), 'm' => $meeting->getDay(0), 't' => $meeting->getDay(1),
'w' => $meeting->getDay(2), 'h' => $meeting->getDay(3), 'f' => $meeting->getDay(4),
's' => $meeting->getDay(5))) . ', '
. json_encode($meeting->instructor_get()) . ', '
. json_encode($meeting->getLocation()) . ', '
. json_encode($meeting->type_get()) . ', '
. json_encode($course_slot->id_get()) . ', '
. json_encode($section->credit_hours_get()) . ');' . PHP_EOL;
@@ -28,22 +28,22 @@ include_once 'inc/class.section.php';
// Supports multiple modes, prettiness, and searching for different indicators
function arrayToDays($array, $mode = 'num', $pretty = false, $key = 1) {
$outString = '';
switch($mode)
case 'short':
$days = array('Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat');
$days = array('Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun');
break;
case 'long':
$days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
$days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
case 'num':
$days = array('1','2','3','4','5');
$days = array('1','2','3','4','5', '6');
case 'alpha':
$days = array('m', 't', 'w', 'h', 'f', 's');
$days = array('m', 't', 'w', 'h', 'f', 's', 'u');
default:
$outString = 'Invalid mode passed to arrayToDays()!';
return $outString;
if(count($array) > 1){
@@ -52,19 +52,27 @@ function arrayToDays($array, $mode = 'nu
if(isset($array[$i]) && $array[$i] == $key){
$outString .= $days[$i];
if($pretty)
$outString .= ', ';
* Sunday is last in the array format (our input, the
* array indices used on the input.php page) but first
* in good/real formats:
if (isset($array[$i]) && $array[$i] == $key)
$outString = $days[$i] . ($pretty ? ', ' : '') . $outString;
if($pretty){
$outString = substr($outString,0,strlen($outString) - 2); // Remove last comma and space
$outString = substr($outString,0, strrpos( $outString, ' ')) . ' and' . substr($outString, strrpos( $outString, ' '), strlen($outString));
else {
for($i=0; $i < 6; $i++)
for($i=0; $i < 7; $i++)
if(isset($array[$i]))
$outString = $days[$i];
@@ -288,12 +288,14 @@ function hope_crawl_semester(array $scho
$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));
if (trim($section_csv[$fields['U']]))
school_crawl_logf($school_crawl_log, 0, "Section %d has sunday.", $synonym);
$days = school_crawl_days_format($school_crawl_log, array_filter(array_slice($section_csv, $fields['M'], 7), '_hope_crawl_days_filter'));
list($time_start, $time_end) = explode('-', $section_csv[$fields['Times']]);
if (strlen($time_start) != 4 || strlen($time_end) != 4)
school_crawl_logf($school_crawl_log, 4, "Section meeting (synonym=%s) has invalidly-formatted start time (%s) or end time (%s). Skipping.",
$synonym, $time_start, $time_end);
@@ -162,27 +162,26 @@ function umich_crawl_semester(array $sch
'M' => FALSE /* if a day is enabled, it is set to itself. I.e., $row['M'] = 'M' or $row['M'] = '' */,
'T' => FALSE,
'W' => FALSE,
'TH' => FALSE,
'F' => FALSE,
'S' => FALSE,
'SU' => FALSE /* OK, we'll have to add Sunday support someday ;-) */,
'SU' => FALSE,
'Start Date' => FALSE /* yea! */,
'End Date' => FALSE /* "12/13/2011" */,
'Time' => FALSE /* "1230-130PM", "9-1030AM", "1130-1PM" */,
'Location' => FALSE,
'Instructor' => FALSE,
'Units' => FALSE /* As in credit hours */,
$ignored_fields = array(
'Term' => TRUE,
'Session' => TRUE,
'Acad Group' => TRUE,
'Codes' => TRUE,
'SU' => TRUE,
foreach (str_getcsv($csv[0]) as $col_num => $col_name)
if (isset($fields[$col_name]))
$fields[$col_name] = $col_num;
else
school_crawl_logf($school_crawl_log, 6, "We do not recognize the %s column in the CSV file for %s.",
@@ -226,13 +225,13 @@ function umich_crawl_semester(array $sch
* calculating credit hours for the user it can present the
* total as a range... not that hard, but still a task ;-).
$credit_hours = (float)$row[$fields['Units']];
$days = '';
foreach (array('M' => 'm', 'T' => 't', 'W' => 'w', 'TH' => 'h', 'F' => 'f', 'S' => 's')
foreach (array('SU' => 'u', 'M' => 'm', 'T' => 't', 'W' => 'w', 'TH' => 'h', 'F' => 'f', 'S' => 's')
as $field => $day)
if (strlen(trim($row[$fields[$field]])))
$days .= $day;
if (!preg_match(';^([0-9]+)-([0-9]+)([AP])M$;', $row[$fields['Time']], $matches))
@@ -197,13 +197,14 @@ function add_section_n(cnum, name, synon
var etime_begin = etime.substr(0, 2);
if (etime_end != '50' && etime_end != '20'
|| etime_begin < 7 || etime_begin > 21)
section_html = section_html + genOptionHtml(etime, prettyTime(etime), etime);
section_html = section_html + '</select></td>\
section_html = section_html + '</select></td>\n\
<td class="cbrow"><input type="checkbox" title="Sunday" class="daysRequired" name="postData[' + cnum +'][' + snum + '][days][6]" value="1" ' + (days.u ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][0]" value="1" ' + (days.m ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][1]" value="1" ' + (days.t ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][2]" value="1" ' + (days.w ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][3]" value="1" ' + (days.h ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][4]" value="1" ' + (days.f ? 'checked="checked"' : '') + ' /></td>\
<td class="cbrow"><input type="checkbox" class="daysRequired" name="postData[' + cnum + '][' + snum + '][days][5]" value="1" ' + (days.s ? 'checked="checked"' : '') + ' /></td>' +
@@ -241,23 +242,25 @@ function add_section_n(cnum, name, synon
section_tr.find('.section-slot-entry').val(slot);
section_tr.find('.profName').val(instructor);
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);
/* unhide the saturday columns if it's used by autocomplete data */
/* unhide the saturday and sunday columns if they're used by autocomplete data */
if (days.u)
jQuery('#jsrows col.sunday').removeClass('collapsed');
if (days.s)
jQuery('#jsrows col.saturday').removeClass('collapsed');
credit_hours_change(cnum);
return last_section_i - 1;
function add_section(cnum)
var section_i = add_section_n(cnum, '', '', '', '', {m: false, t: false, w: false, h: false, f: false, s: false}, '', '', '', 'default', -1);
var section_i = add_section_n(cnum, '', '', '', '', {}, '', '', '', 'default', -1);
if (cnum == slate_permutate_course_free)
course_free_check(cnum);
return section_i;
@@ -337,13 +340,13 @@ function course_add_slot_row(course_i, s
if (!show_course_slots[course_i])
extra_classes += ' tr-slot-id-hidden';
jQuery('tr.class' + course_i + ':last').after(
'<tr class="class' + course_i + ' tr-slot-id ' + safe_css_class('slot-' + slot_id) + extra_classes + '">\n' +
' <td><span /></td>\n' +
' <td colspan="10"><span class="slot-id-text" /></td>\n' +
' <td colspan="11"><span class="slot-id-text" /></td>\n' +
' <td colspan="2"><span /></td>\n' +
'</tr>\n'
jQuery('tr.class' + course_i + ':last .slot-id-text').text('The following are ' + slot_id + ' sections and will be scheduled as a group.');
@@ -382,13 +385,13 @@ function add_class_n(course_id, title)
if (course_id.length && slate_permutate_course_free != -1)
course_remove(slate_permutate_course_free);
sectionsOfClass[classNum] = 0; // Initialize at 0
course_ajax_requests[classNum] = false;
jQuery('#jsrows').append('<tr id="tr-course-' + classNum + '" class="class class' + classNum + ' pclass' + classNum + '"><td class="nameTip"><input type="text" id="input-course-' + classNum + '" class="classRequired defText className'+classNum+' className" title="Class Name" name="postData[' + classNum + '][name]" /></td><td colspan="10"><input type="text" name="postData[' + classNum + '][title]" class="inPlace inPlace-enable course-title-entry input-submit-disable" /><span class="course-credit-hours course-credit-hours-' + classNum + '"></span></td><td class="tdInput"><div class="deleteClass"><input type="button" value="Remove" class="gray" /></div></td><td class="none"><button type="button" class="addSection gray">+</button></td></tr>');
jQuery('#jsrows').append('<tr id="tr-course-' + classNum + '" class="class class' + classNum + ' pclass' + classNum + '"><td class="nameTip"><input type="text" id="input-course-' + classNum + '" class="classRequired defText className'+classNum+' className" title="Class Name" name="postData[' + classNum + '][name]" /></td><td colspan="11"><input type="text" name="postData[' + classNum + '][title]" class="inPlace inPlace-enable course-title-entry input-submit-disable" /><span class="course-credit-hours course-credit-hours-' + classNum + '"></span></td><td class="tdInput"><div class="deleteClass"><input type="button" value="Remove" class="gray" /></div></td><td class="none"><button type="button" class="addSection gray">+</button></td></tr>');
/* store classNum as course_i into the <tr />: */
var tr_course = jQuery('#tr-course-' + classNum);
tr_course.data({course_i: classNum});
tr_course.find('.course-title-entry').val(title);
tr_course.find('.className').val(course_id);
Status change: