Changeset - 84dacca3fe10
[Not reviewed]
default
0 3 0
Nathan Brink (binki) - 13 years ago 2013-01-27 03:20:24
ohnobinki@ohnopublishing.net
Automatically determine a suggested example course_id based on the number of sections found in a course during crawling, bug #102.
3 files changed with 80 insertions and 17 deletions:
0 comments (0 inline, 0 general)
inc/admin.inc
Show inline comments
 
@@ -125,54 +125,55 @@ function school_cache($schools)
 
       * want to run all crawlers ;-).
 
       */
 
      if (!empty($school['crawled']) && !isset($school['crawled_notreally']))
 
	{
 
	  $cache_auto_school_dir_name = $cache_auto_dir_name . $school['id'] . DIRECTORY_SEPARATOR;
 
	  if (!is_dir($cache_auto_school_dir_name))
 
	    {
 
	      if (!mkdir($cache_auto_school_dir_name, 0755, TRUE))
 
		error_log('Unable to create needed directory: `' . $cache_auto_dir_name . '\'');
 
	    }
 

	
 
	  $semesters = array();
 
	  $semester_weights = 0;
 
	  /*
 
	   * Try to presort the semesters into the proper order based
 
	   * on time_start/time_end. We want the older semesters to be
 
	   * nearer to the end of the list. This way, the crawler
 
	   * doesn't have to decide how to sort the semesters itself:
 
	   */
 
	  usort($semesters, 'school_cache_semesters_sort');
 

	
 
	  foreach ($school['crawled_semesters'] as $semester)
 
	    {
 
	      $semesters[$semester->id()] = array(
 
						  'id' => $semester->id(),
 
						  'time_start' => $semester->time_start_get(),
 
						  'time_end' => $semester->time_end_get(),
 
						  'weight' => $semester_weights ++,
 
						  'name' => $semester->name_get(),
 
						  );
 
		'id' => $semester->id(),
 
		'popular_course_id' => $semester->popular_course_id_get(),
 
		'name' => $semester->name_get(),
 
		'time_start' => $semester->time_start_get(),
 
		'time_end' => $semester->time_end_get(),
 
		'weight' => $semester_weights ++,
 
	      );
 
	    } /* foreach ( => $semester) */
 
	  /*
 
	   * Store/cache the semester metadata:
 
	   */
 
	  $semesters_file = fopen($cache_auto_school_dir_name . '-semesters', 'wb');
 
	  fwrite($semesters_file, serialize($semesters));
 
	  fclose($semesters_file);
 
	}
 
    }
 
  uasort($list_cache, 'school_cmp');
 

	
 
  $cache = array('list' => $list_cache, 'domains' => $domain_cache);
 

	
 
  $cache_file_name =  $cache_dir_name . 'schools';
 
  $cache_file = fopen($cache_file_name, 'wb');
 
  if ($cache_file === FALSE)
 
    {
 
      fprintf(STDERR, "Unable to open `%s' for writing\n",
 
	      $cache_file_name);
 
      return 1;
 
    }
 
  fwrite($cache_file, serialize($cache));
 
  fclose($cache_file);
 

	
inc/class.semester.inc
Show inline comments
 
@@ -59,73 +59,82 @@ class Semester
 
   *   Semester::SEASON_FALL, Semester::SEASON_SPRING, or
 
   *   Semester::SEASON_SUMMER if possible.
 
   * \param $time_start
 
   *   Specify a timestamp which roughly estimates when this semester
 
   *   starts to aid the algorithm for guessing the current
 
   *   semester. See Semester::time_start_set(), which may be used
 
   *   instead of this parameter
 
   * \param $time_end
 
   *   This may be specified now or via Semester::time_end_set().
 
   */
 
  function __construct($year, $season, $time_start = 0, $time_end = 0)
 
  {
 
    $this->time_start = 0;
 
    $this->time_end = 0;
 
    $this->time_starts = array();
 
    $this->time_ends = array();
 
    $this->season = $season;
 

	
 
    if (strlen($year) != 4 || !is_numeric($year))
 
      throw new ErrorException('Attempt to construct a Semester with an invalid year. The given year is `' . $year . '\'');
 
    $this->year = $year;
 

	
 
    $this->departments = array();
 
    $this->department_names = array();
 

	
 
    /*
 
     * For $this->popular_course_get().
 
     */
 
    $this->course_num_sections_map = array();
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Add a class to this Semester.
 
   *
 
   * \param $class
 
   *   The class/course to add.
 
   */
 
  public function class_add(Course $class)
 
  public function class_add(Course $course)
 
  {
 
    $class_parts = Course::parse($class->getName());
 
    if (!isset($class_parts['course']))
 
      throw new ErrorException('I was given a class with an invalid name: `' . $class->getName() . '\'');
 
    $course_parts = Course::parse($course->getName());
 
    if (!isset($course_parts['course']))
 
      throw new ErrorException('I was given a class with an invalid name: `' . $course->getName() . '\'');
 

	
 
    foreach ($class as $course_slot)
 
    foreach ($course 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']];
 
        $this->_section_count($course, $section);
 
      }
 

	
 
    $department[$class_parts['course']] = $class;
 
    if (!isset($this->departments[$course_parts['department']]))
 
      $this->departments[$course_parts['department']] = array();
 
    $department =& $this->departments[$course_parts['department']];
 

	
 
    $department[$course_parts['course']] = $course;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Retrieve a class.
 
   *
 
   * \param $dept
 
   *   The class's department. 'CS' for 'CS-262'.
 
   * \param $class
 
   *   The course/class number. '262' for 'cs-262'.
 
   * \return
 
   *   A Course or NULL if not found.
 
   */
 
  public function class_get($dept, $class)
 
  {
 
    if (!isset($this->departments[$dept][$class]))
 
      return NULL;
 

	
 
    return $this->departments[$dept][$class];
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Gets a list of departments available in this semester.
 
@@ -223,48 +232,50 @@ class Semester
 
   *   does not have the concept of course slots. Ask binki for help
 
   *   figuring this out. Course slots are a sort of
 
   *   inverse/complement to section_meetings.
 
   */
 
  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);
 

	
 
    if (!isset($this->departments[$dept])
 
	|| !isset($this->departments[$dept][$class]))
 
      {
 
	$classobj = new Course($dept . '-' . $class, $title);
 
	$this->class_add($classobj);
 
      }
 
    else
 
      {
 
	$classobj = $this->departments[$dept][$class];
 
      }
 

	
 
    $classobj->section_add($section, $course_slot_id);
 

	
 
    $this->_section_count($classobj, $section);
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Add a section_meeting, calling Semester::section_add() as
 
   *   necessary.
 
   *
 
   * To be used by crawlers when parsing data which only presents one
 
   * section_meeting at a time. I.e., when they do tabular data right.
 
   *
 
   * \param $dept
 
   *   The department this section_meeting's course belongs to.
 
   * \param $course
 
   *   The course number this section_meeting's section belongs to.
 
   * \param $title
 
   *   The course title of the given course the section_meeting or
 
   *   NULL. If the section has already been added, this parameter
 
   *   will be ignored.
 
   * \param $section
 
   *   The letter or numbers which make up the section's name.
 
   * \param $synonym
 
   *   The section synonym or NULL.
 
   * \param $section_meeting
 
   *   The SectionMeeting to be added to a section which may or may
 
@@ -278,48 +289,88 @@ class Semester
 
   */
 
  public function section_meeting_add($dept, $course, $title, $section, $synonym, SectionMeeting $section_meeting, $course_slot_id = 'default', $credit_hours = -1.0)
 
  {
 
    $this->time_set_section_meeting($section_meeting);
 

	
 
    $dept = strtoupper($dept);
 
    $course = strtoupper($course);
 

	
 
    if (empty($this->departments[$dept][$course]))
 
      $course_obj = NULL;
 
    else
 
      {
 
	$course_obj = $this->departments[$dept][$course];
 
	$section_obj = $course_obj->section_get($section);
 
      }
 
    if (empty($course_obj) || empty($section_obj))
 
      return $this->section_add($dept, $course, new Section($section, array($section_meeting), $synonym, $credit_hours), $title, $course_slot_id);
 

	
 
    $section_obj->meeting_add($section_meeting);
 
    return;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Account for the addition of a new section to this Semester.
 
   *
 
   * \param $course
 
   *   The course this section is a part of.
 
   * \param $section
 
   *   The section.
 
   */
 
  private function _section_count(Course $course, Section $section)
 
  {
 
    $fully_qualified_course_id = $course->getName();
 
    $this->course_num_sections_map += array($fully_qualified_course_id => 0);
 
    $this->course_num_sections_map[$fully_qualified_course_id] ++;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Get the most popular course.
 
   *
 
   * \return
 
   *   The fully-qualified course_id of the most popular course in
 
   *   this Semester.
 
   */
 
  public function popular_course_id_get()
 
  {
 
    if (count($this->course_num_sections_map))
 
      {
 
        arsort($this->course_num_sections_map, SORT_NUMERIC);
 
        reset($this->course_num_sections_map);
 
        $this->_popular_course = key($this->course_num_sections_map);
 
      }
 
    if (!isset($this->_popular_course))
 
      {
 
        /* The default popular course */
 
        $this->_popular_course = 'ENGL-101';
 
      }
 
    return $this->_popular_course;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Update the time_end.
 
   *
 
   * The time_end is a unix timestamp roughly estimating the time at
 
   * which a semester starts. It is used when guessing what semester a
 
   * user is interested in.
 
   *
 
   * \param $time_end
 
   *   The new time_end.
 
   */
 
  public function time_end_set($time_end)
 
  {
 
    $this->time_end = $time_end;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Set the time_end only if it would make the semester end later.
 
   *
 
   * Useful for crawler scripts incrementally guessing the endtime of
 
   * a semester.
 
   *
 
   * \param $time_end
 
   *   The new time_end to consider.
 
   */
 
@@ -506,26 +557,35 @@ class Semester
 
  /**
 
   * \brief
 
   *   Enumerate all valid seasons.
 
   */
 
  public static function seasons_get_all()
 
  {
 
    return array(self::SEASON_SPRING, self::SEASON_SUMMER, self::SEASON_FALL);
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Clean the semester of all sections, keeping metadata intact.
 
   */
 
  public function purge()
 
  {
 
    $this->departments = array();
 
    /*
 
     * Make sure that time_end is set to the proper end time before
 
     * clearing out the pool in the time_ends array.
 
     */
 
    $this->time_end_get();
 
    $this->time_ends = array();
 
    $this->time_start_get();
 
    $this->time_starts = array();
 

	
 
    /*
 
     * A mapping which keeps track of how many sections any given
 
     * course has, with course_id '-' section_id as the key and the
 
     * count as the value. Used to calculate the most frequently-used
 
     * course_id to use as the example course_id (bug #102).
 
     */
 
    $this->popular_course_id_get();
 
    $this->course_num_sections_map = array();
 
  }
 
}
input.php
Show inline comments
 
@@ -93,50 +93,52 @@ elseif (!empty($_REQUEST['e']))
 
	$school = school_load($postData['school']);
 
	if (!empty($school))
 
	  $inputPage_options['school'] = $school;
 
      }
 

	
 
    if (!empty($school) && !empty($postData['semester']))
 
      {
 
	$semesters = school_semesters($school);
 
	if (!empty($semesters[$postData['semester']]))
 
	  $inputPage_options['semester'] = $semester;
 
      }
 

	
 
    $creating_new_schedule = FALSE;
 
  }
 

	
 
/*
 
 * We cannot initialize the page object nor guess the school before
 
 * figuring loading a saved schedule because we'll default to that
 
 * saved_schedule's school/semester.
 
 */
 
$scripts = array('jQuery', 'jQueryUI', 'qTip2', 'schedInput');
 
$inputPage = page::page_create('Enter Courses', $scripts, $inputPage_options);
 
$school = $inputPage->get_school();
 
$semester = $inputPage->semester_get();
 
if (empty($semesters))
 
  $semesters = school_semesters($school);
 

	
 
$my_hc = 'var slate_permutate_example_course_id = ' . json_encode(school_example_course_id($school)) . ';
 
$my_hc = 'var slate_permutate_example_course_id = ' . json_encode(empty($semester) || empty($semester['popular_course_id']) ? school_example_course_id($school) : $semester['popular_course_id']) . ';
 

	
 
jQuery(document).ready(
 
  function()
 
  {
 
    var class_last = 0;
 

	
 
';
 
if ($sch)
 
{
 
  foreach ($sch->courses_get() as $course)
 
    {
 
      $my_hc .= input_course_js($course, '    ');
 
    }
 
}
 
elseif ($errors_fix)
 
  {
 
    foreach ($_POST['postData'] as $course)
 
      if (is_array($course))
 
	{
 
	  $title = '';
 
	  if (!empty($course['title']))
 
	    $title = $course['title'];
 
	  if (empty($course['name']))
 
	    $my_hc .= '    class_last = add_class();' . PHP_EOL;
 
@@ -249,49 +251,49 @@ if (!empty($_REQUEST['selectsemester']))
 
  $next_page = 'input.php?';
 
  if (isset($_GET['s']))
 
    $next_page .= 's=' . (int)$_GET['s'] . '&';
 
  if (!empty($_GET['school']))
 
    $next_page .= 'school=' . $_GET['school'] . '&';
 

	
 
  $inputPage->showSemesters($next_page);
 
  $inputPage->foot();
 
  exit;
 
  }
 

	
 
$inputPage->showSavedScheds($_SESSION);
 
?>
 

	
 
<?php if (!empty($input_warning_banner)): ?>
 
<div class="warning">
 
  <?php echo $input_warning_banner; ?>
 
</div>
 
<?php endif; ?>
 

	
 
<p>
 
  Welcome to SlatePermutate<?php $inputPage->addressStudent(', ', '', FALSE); ?>!
 
  <?php if (school_has_auto($inputPage->get_school())): ?>
 
  To get started, enter in a course identifier (e.g., <em>
 
  <?php echo school_example_course_id($inputPage->get_school()); ?></em>)
 
  <?php echo empty($semester) || empty($semester['popular_course_id']) ? school_example_course_id($inputPage->get_school()) : $semester['popular_course_id']; ?></em>)
 
  and click the autosuggestion to automatically load available sections
 
  for each class.
 
  <?php else: ?>
 
  To get started, enter a course number and add some sections to it.
 
  Then specify each section's letter/number and what times it meets,
 
  add more courses, and click &ldquo;Find a Schedule&rdquo;.
 
  <!--'-->
 
  <?php endif; ?>
 
</p>
 

	
 
<form method="post" action="process.php" id="scheduleForm">
 
<p class="nospace" style="border-left: 5px solid #999; padding-left: 5px!important; padding-top: 5px!important;"><label>Schedule Name</label><br />
 
<input
 
    id="scheduleName"
 
    style="margin-bottom: 1em;"
 
    class="defText required input-submit-disable"
 
    type="text"
 
    size="25"
 
    title="My <?php echo $semester['name']; ?> Schedule"
 
    name="postData[name]"
 
    <?php
 
      if ($sch)
 
        echo 'value="' . htmlentities($sch->getName(), ENT_QUOTES) . '"';
 
      elseif ($errors_fix)
0 comments (0 inline, 0 general)