Changeset - d903bd3d579e
[Not reviewed]
default
0 3 5
Nathan Brink (binki) - 15 years ago 2010-10-09 01:54:03
ohnobinki@ohnopublishing.net
Add school profiles support. Currently, the only significant thing school profiles does is provide a different blog of HTML at the bottom of the input.php page so that users may receive school-specific instructions on how to use slate_permutate. School profiles _will_ be extended to provide autocompletion of sections for a specific course based on previously crawling a college's registration website. All-in-all, it maintains a simple school_id string which can be used by other components to uniquely identify a school for any arbitrary purpose.
8 files changed with 621 insertions and 1 deletions:
0 comments (0 inline, 0 general)
.hgignore
Show inline comments
 
@@ -2,6 +2,8 @@ style: regex
 

	
 
# ignore all saved schedules, but keep track of the .keep file.
 
^saved_schedules/[^.]
 
# ignore all of cache except for the .keep file
 
^cache/[^.]
 

	
 
# ignore common unwanted suffixes
 
(~|\.orig|\.rej)$
admin/rehash.php
Show inline comments
 
new file 100755
 
#!/usr/bin/env php
 
<?php
 
/*
 
 * Copyright 2010 Nathan Phillip Brink <ohnobinki@ohnopublishing.net>
 
 *
 
 * This file is a part of slate_permutate.
 
 *
 
 * slate_permutate is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * slate_permutate is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with slate_permutate.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/**
 
 * \file
 
 *
 
 * Runs through schools.d grabbing and caching data, such as the
 
 * school listing used for the ``choose your school list''.
 
 */
 

	
 
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'school.inc');
 
return main($argc, $argv);
 

	
 
function main($argc, $argv)
 
{
 
  $school_id_list = school_list();
 
  if (!$school_id_list)
 
    return 1;
 

	
 
  $schools = array();
 
  foreach ($school_id_list as $school_id)
 
    {
 
      $school = school_load($school_id);
 
      if (!$school)
 
	{
 
	  fprintf(STDERR, "Error loading school with school_id=%s\n",
 
		  $school_id);
 
	  return 1;
 
	}
 
      $schools[] = $school;
 
    }
 

	
 
  if (school_cache($schools))
 
    {
 
      fprintf(STDERR, "Error writing out school cache\n");
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 
/*
 
 * functions which are only needed when recreating the cache.
 
 */
 

	
 
/**
 
 * \brief
 
 *   Returns the list of available school IDs or NULL on error.
 
 */
 
function school_list()
 
{
 
  $schoold_dir_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'school.d';
 
  $schoold_dir = opendir($schoold_dir_name);
 
  if ($schoold_dir === FALSE)
 
    {
 
      fprintf(STDERR, "Unable to open school.d directory. Was using path: `%s'\n",
 
	      $schoold_dir_Name);
 
      return NULL;
 
    }
 

	
 
  $school_id_list = array();
 
  while ($filename = readdir($schoold_dir))
 
    {
 
      if (!preg_match('/^([a-z0-9]+)\.inc$/', $filename, $matches))
 
	continue;
 

	
 
      $school_id_list[] = $matches[1];
 
    }
 

	
 
  closedir($schoold_dir);
 

	
 
  return $school_id_list;
 
}
 

	
 
/**
 
 * \brief
 
 *   Write out the cache file which remembers the list of available
 
 *   schools.
 
 *
 
 * \todo
 
 *   If the list of displayed schools is to be sorted, this is the
 
 *   place to do it.
 
 *
 
 * \param $schools
 
 *   An array of school handles.
 
 */
 
function school_cache($schools)
 
{
 
  $list_cache = array();
 
  $domain_cache = array();
 
  foreach ($schools as $school)
 
    {
 
      $list_cache[$school['id']] = array(
 
					 'name' => $school['name'],
 
					 'url' => $school['url'],
 
					 );
 
      foreach ($school['domains'] as $school_domain)
 
	{
 
	  $domain_cache_ptr =& $domain_cache;
 

	
 
	  $domain_parts = array_reverse(explode('.', $school_domain));
 
	  while (count($domain_parts) > 1)
 
	    {
 
	      $domain_part = array_shift($domain_parts);
 
	      if (!isset($domain_cache_ptr[$domain_part])
 
		  || !is_array($domain_cache_ptr[$domain_part]))
 
		$domain_cache_ptr[$domain_part] = array();
 
	      $domain_cache_ptr =& $domain_cache_ptr[$domain_part];
 
	    }
 
	  /*
 
	   * get the last part which is unambiguously identifies this
 
	   * school combined with the previous parts
 
	   */
 
	  $domain_part = array_shift($domain_parts);
 
	  $domain_cache_ptr[$domain_part] = $school['id'];
 
	}
 
    }
 

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

	
 

	
 
  $cache_file_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
 
    . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . '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);
 

	
 
  return 0;
 
}
cache/.keep
Show inline comments
 
new file 100644
inc/class.page.php
Show inline comments
 
@@ -29,8 +29,13 @@ class page
 
  private $pagetitle = ''; // Title of page
 
  private $scripts = array(); // Scripts to include on page
 

	
 
  /* the current school. See get_school(). */
 
  private $school;
 

	
 
  public function __construct($ntitle, $nscripts = array(), $immediate = TRUE)
 
  {
 
    require_once('school.inc');
 

	
 
    // Scripts and styles available to include
 
    $this->headCode['jQuery'] = '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript" />';
 
    $this->headCode['jQueryUI'] = '<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7/jquery-ui.min.js" type="text/javascript" /><link rel="stylesheet" href="styles/jqueryui.css" type="text/css" media="screen" charset="utf-8" />';
 
@@ -62,6 +67,10 @@ class page
 
    if($immediate
 
       && $ntitle != "NOHEAD")
 
      $this->head();
 

	
 
    /* everything that needs sessions started to work: */
 

	
 
    $this->school = school_load_guess();
 
 }
 

	
 
  /**
 
@@ -162,6 +171,65 @@ class page
 

	
 
  /**
 
   * \brief
 
   *   Display a list of schools the user might be from.
 
   * \param $linkto
 
   *   The to which a &school= or ?school= query string should be
 
   *   appended.
 
   */
 
  public function showSchools($linkto)
 
  {
 
    echo "<p>\n";
 
    echo "  <div id=\"schoolBox\">\n";
 
    echo school_list_html($this->school['id'], $linkto);
 
    echo "  </div> <!-- id=\"schoolBox\" -->\n";
 
    echo "</p>\n";
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Display school-specific instructions for using slate_permutate.
 
   */
 
  public function showSchoolInstructions()
 
  {
 
    echo "<div id=\"schoolInstructionsBox\">\n";
 
    echo school_instructions_html($this->school);
 
    echo "</div> <!-- id=\"schoolInstructionsBox\" -->\n";
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Print out a vocative form of a student's identity. For example,
 
   *   Dearborn Christin Schoolers are called ``Knights'' as are
 
   *   Calvin College students.
 
   *
 
   * The third argument is used to determine whether or not this
 
   * address _needs_ to be printed out. For example, in some sentences
 
   * when addressing generic students, it makes no sense to say the
 
   * standard ``Welcome, student'' or ``Dear generic person, how do
 
   * you do today?''. If the third argument is false, we'll refrain
 
   * from outputting anything at all.
 
   *
 
   * \param $prefix
 
   *   If the address is to be printed, output this beforehand. Useful
 
   *   if this prefix shouldn't be printed if the address itself isn't
 
   *   to be printed. See $necessary.
 
   * \param $postfix
 
   *   Text to print after the address if it's printed.
 
   * \param $necessary
 
   *   Whether or not we might ignore the request that an address be
 
   *   printed in certain cases. We default to always printing the
 
   *   address.
 
   */
 
  public function addressStudent($prefix = '', $postfix = '', $necessary = TRUE)
 
  {
 
    if (!$necessary && $this->school['id'] == 'default')
 
      return;
 

	
 
    echo $prefix . $this->school['student_address'] . $postfix;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Display a 404 page and halt the PHP interpreter.
 
   *
 
   * This function does not return. It handles the creation of a Page
 
@@ -185,4 +253,13 @@ class page
 

	
 
    exit();
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Get the current school profile handle.
 
   */
 
  public function get_school()
 
  {
 
    return $this->school;
 
}
 
}
inc/school.inc
Show inline comments
 
new file 100644
 
<?php
 
/*
 
 * Copyright 2010 Nathan Phillip Brink <ohnobinki@ohnopublishing.net>
 
 *
 
 * This file is a part of slate_permutate.
 
 *
 
 * slate_permutate is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * slate_permutate is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with slate_permutate.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/**
 
 * \file
 
 *
 
 * Provide a method of storing and retrieving school-specific
 
 * information. Identifying schools is intended to be useful for
 
 * obtaining and storing preknowledge of the sections a school offers
 
 * to allow easier input.
 
 *
 
 * Anything code specific to a particular school should be placed in a
 
 * file in the school.d directory. The filename shall be the short,
 
 * alphanumeric, machine-usable school identifier followed by
 
 * ``.inc''. This allows optimized loading of school-specific routines
 
 * when the identifier is already known.
 
 */
 

	
 
/**
 
 * \brief
 
 *   Load a school profile based on its identifier.
 
 *
 
 * This function loads the school's description file and asks for info
 
 * from a callback called $school_id . '_info' which must return an
 
 * array with the following keys:
 
 * - name: a friendly name for the school. Must be a valid XHTML attribute string.
 
 * - url: the school's website URL as a valid XHTML attribute string. (i.e., escape ampersands).
 
 *
 
 * \param $school_id
 
 *   The school's alphanumeric identifier (which determines the name
 
 *   of the school's *.inc file).
 
 * \return
 
 *   A school_profile handle or NULL on error.
 
 */
 
function school_load($school_id)
 
{
 
  $school = array('id' => $school_id);
 

	
 
  /* guard against cracking attempts (protects against '../' and friends) */
 
  if (!preg_match('/^[0-9a-z]+$/', $school_id))
 
    return NULL;
 
  $school_file_name = dirname(__FILE__) . DIRECTORY_SEPARATOR
 
    . '..' . DIRECTORY_SEPARATOR . 'school.d' . DIRECTORY_SEPARATOR . $school_id . '.inc';
 

	
 
  if (!file_exists($school_file_name))
 
    return NULL;
 

	
 
  require_once($school_file_name);
 

	
 
  $school_info = $school_id . '_info';
 
  $school += $school_info();
 

	
 
  return $school;
 
}
 

	
 
/**
 
 * \brief
 
 *   Tries to guess what school a connection comes from.
 
 *
 
 * This function checks if $_REQUEST['school'] is set to a valid
 
 * school, so that the user can manually choose his school. Then it
 
 * chcecks if the user's session specifies what school profile to
 
 * use. Then it tries to make a best guess as to the school he's from
 
 * using the rDNS information provided by the httpd.
 
 *
 
 * \return
 
 *   A school profile or NULL if the school isn't in the session and
 
 *   can't be guessed.
 
 */
 
function school_load_guess()
 
{
 
  if (isset($_REQUEST['school']))
 
    {
 
      $school = school_load($_REQUEST['school']);
 
      if ($school)
 
	{
 
	  $_SESSION['school'] = $school['id'];
 
	  return $school;
 
	}
 
    }
 

	
 
  /* assume that we stored a valid school in the $_SESSION */
 
  if (isset($_SESSION['school']))
 
    return school_load($_SESSION['school']);
 

	
 
  if (isset($_SERVER['REMOTE_HOST']) || isset($_SERVER['REMOTE_ADDR']))
 
    {
 
      $addr = NULL;
 
      if (!isset($_SERVER['REMOTE_HOST']))
 
	$addr = gethostbyaddr($_SERVER['REMOTE_ADDR']);
 

	
 
      $cache = _school_cache_load();
 
      if ($addr && $cache && count($cache['domains']))
 
	{
 
	  $domain_parts = array_reverse(explode('.', $addr));
 
	  $domain_school = $cache['domains'];
 
	  while (is_array($domain_school))
 
	    {
 
	      $domain_part = array_shift($domain_parts);
 
	      if (isset($domain_school[$domain_part]))
 
		$domain_school = $domain_school[$domain_part];
 
	      else
 
		$domain_school = NULL;
 
	    }
 
	  /*
 
	   * by now, $domain_school is either NULL or the school_id of
 
	   * the school we want.
 
	   */
 
	  if ($domain_school)
 
	    {
 
	      $school = school_load($domain_school);
 
	      if ($school)
 
		{
 
		  $_SESSION['school'] = $domain_school;
 
		  return school_load($domain_school);
 
		}
 
	    }
 
	}
 
    }
 

	
 
  /*
 
   * set something in $_SESSION so that the gethostbyaddr() call
 
   * doesn't have to be done too often. (the isset() call above should
 
   * detect even the empty string).
 
   */
 
  $_SESSION['school'] = 'default';
 

	
 
  /* loading the school_id of 'default' MUST always work */
 
  return school_load($_SESSION['school']);
 
}
 

	
 
/**
 
 * \brief
 
 *   Render a list of school profile choices.
 
 *
 
 * Loads the list of schools and transforms the list into HTML,
 
 * optionally highlighting a specified school.
 
 *
 
 * The list of schools includes links to the specified destination,
 
 * appending a &school= to the query string. This is intended to work
 
 * in conjunction with school_load_guess() to allow the user to
 
 * manually choose his school.
 
 *
 
 * \param $highlight
 
 *   The school_id of the school whose list entry should be
 
 *   highlighted or NULL to avoid highlighting any entry.
 
 * \param $linkto
 
 *   Each school entry shall be a link for the user to switch which
 
 *   school profile he's using. This is to specify the URL or page
 
 *   these links should point to (the rest is handled by
 
 *   school_load_guess()). We will call htmlentities() for you.
 
 * \return
 
 *   An HTML formatted list of school profile choices where each entry
 
 *   is a link setting the client's choice to the specified school.
 
 */
 
function school_list_html($highlight = NULL, $linkto = NULL)
 
{
 
  $cache = _school_cache_load();
 
  if (!$cache || !count($cache['list']))
 
    return NULL;
 
  $school_list = $cache['list'];
 

	
 
  /* form the query string for the links */
 
  if (!$linkto)
 
    $linkto = '?';
 
  elseif (strpos($linkto, '?') === FALSE)
 
    $linkto .= '?';
 
  else
 
    $linkto .= '&';
 
  $linkto .= 'school=';
 
  $linkto = htmlentities($linkto);
 

	
 
  $html = "<ul>\n";
 
  foreach ($school_list as $school_id => $school_info)
 
    {
 
      $class_highlight = '';
 
      if ($school_id == $highlight)
 
	$class_highlight = ' highlight';
 
      $html .= '<li class="school' . $class_highlight . '"><a href="' . $linkto . $school_id . '">'
 
	. $school_info['name'] . "</a></li>\n";
 
    }
 
  $html .= "</ul>\n";
 

	
 
  return $html;
 
}
 

	
 
/**
 
 * \brief
 
 *   Get a school-specific information page.
 
 *
 
 * Each school may define a function called
 
 * <school_id>_instructions_html(). This is the wrapper which retrieves a
 
 * specific school's info HTML. It is recommended that instructions
 
 * about using the school's registration system in conjunction with
 
 * slate_permutate be placed in the instructions_html.
 
 *
 
 * \param $school
 
 *   A school handle obtained from school_load() or
 
 *   school_load_guess().
 
 * \return
 
 *   An HTML fragment of the school's information or NULL if the
 
 *   school either doesn't have any such information or if the school
 
 *   handle is invalid.
 
 */
 
function school_instructions_html($school)
 
{
 
  if (!$school || !$school['id']
 
      || !function_exists($school['id'] . '_instructions_html'))
 
    return NULL;
 

	
 
  $school_instructions_html = $school['id'] . '_instructions_html';
 
  return $school_instructions_html();
 
}
 

	
 
/**
 
 * \brief
 
 *   Used to load the school cache.
 
 *
 
 * \return
 
 *   The cache array or NULL if the cache couldn't be loaded.
 
 */
 
function _school_cache_load()
 
{
 
  static $cache = NULL;
 

	
 
  if ($cache != NULL)
 
    return $cache;
 

	
 
  $cache_file_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
 
    . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'schools';
 
  $cache_serialized = @file_get_contents($cache_file_name);
 
  if (isset($cache_serialized))
 
    $cache = unserialize($cache_serialized);
 

	
 
  return $cache;
 
}
input.php
Show inline comments
 
@@ -39,9 +39,39 @@ var sectionsOfClass = Array();
 
// </script>', TRUE);
 

	
 
$inputPage->head();
 

	
 
/*
 
 * Force a student to choose a school or declare he's a generic
 
 * student before displaying the input form.
 
 */
 
$school = $inputPage->get_school();
 
if ($_REQUEST['setted'] == 1 || $school['id'] != 'default')
 
  $_SESSION['school_setted'] = TRUE;
 
if ($_REQUEST['selectschool'] == 1
 
    || $school['id'] == 'default' && !isset($_SESSION['school_setted']))
 
  {
 
?>
 
<h2>School Selection</h2>
 
<p>
 
  Choose the school you attend from the list below. <b>If you cannot
 
  find your school</b>, you may proceed using
 
  the <a href="input.php?school=default&amp;setted=1">generic
 
  settings</a>.
 
</p>
 
<?php
 
    $inputPage->showSchools('input.php?setted=1');
 
    $inputPage->foot();
 
    exit;
 
  }
 

	
 
$inputPage->showSavedScheds($_SESSION);
 
?>
 
<p>Welcome to SlatePermutate! To get started, enter in some of your classes, and add available sections for each class.</p>
 
<p>
 
  Welcome to SlatePermutate<?php $inputPage->addressStudent(', ', '',
 
  FALSE); ?>! (<a href="input.php?selectschool=1">Not from <?php echo
 
  $school['name']; ?>?</a>) To get started, enter in some of your
 
  classes, and add available sections for each class.
 
</p>
 
<p style="color: #999"><em>Keyboard Shortcut: Press "c" to add a class</em></p>
 
<form method="post" action="process.php" id="scheduleForm">
 
<br />
 
@@ -82,4 +112,5 @@ var sectionsOfClass = Array();
 
<p>&nbsp;<br /><br /><br /></p>
 
<?php /* RE-enable if advanced options added: <p><span id="showadvanced" style="margin-left: 1em;"><a href="#">Advanced</a></span></p> */ ?>
 
<?php
 
$inputPage->showSchoolInstructions();
 
$inputPage->foot();
school.d/calvin.inc
Show inline comments
 
new file 100644
 
<?php
 
/*
 
 * Copyright 2010 Nathan Phillip Brink <ohnobinki@ohnopublishing.net>
 
 *
 
 * This file is a part of slate_permutate.
 
 *
 
 * slate_permutate is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * slate_permutate is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with slate_permutate.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
function calvin_info()
 
{
 
  return array('name' => 'Calvin College',
 
	       'url' => 'http://calvin.edu/',
 
	       /*
 
		* rDNS postfixes which indicate a student is
 
		* connecting from that college campus
 
		*/
 
	       'domains' => array(
 
				  'calvin.edu',
 
				  ),
 
	       'student_address' => 'Knight',
 
	       );
 
}
 

	
 
function calvin_instructions_html()
 
{
 
  return <<<EOF
 
<h2>Calvin-specific Instructions</h2>
 
<p>
 
  <tt>slate_permutate</tt> can be a useful tool for scheduling your next semester at <a href="http://calvin.edu/">Calvin College</a>.
 
</p>
 
<ol>
 
  <li>Get in touch with your advisor during advising/reading recess.</li>
 
  <li>Look up each class your advisor specified in Calvin's registration page of <a href="http://kv.calvin.edu/">KnightVision</a> (soon to be <a href="http://moodle.calvin.edu">moo</a>).</li>
 
  <li>Enter each class into a <tt>slate_permutate</tt> schedule and add each section that is listed that you are willing to take.</li>
 
  <li>Submit your schedule and view all of the different permutations of your schedule which would work with the sections you specified.</li>
 
  <li>Print our your preferred schedule by selecting a schedule an choosing your User-Agent's print option.</li>
 
  <li>Wait until it's your turn to register and grab your preferred sections before they fill up!</li>
 
</ol>
 
EOF;
 
}
school.d/default.inc
Show inline comments
 
new file 100644
 
<?php
 
/*
 
 * Copyright 2010 Nathan Phillip Brink <ohnobinki@ohnopublishing.net>
 
 *
 
 * This file is a part of slate_permutate.
 
 *
 
 * slate_permutate is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * slate_permutate is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with slate_permutate.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
function default_info()
 
{
 
  return array('name' => 'Generic College',
 
	       'url' => 'http://example.edu/',
 
	       /*
 
		* rDNS postfixes which indicate a student is
 
		* connecting from that college campus.
 
		*/
 
	       'domains' => array(
 
				  ),
 
	       'student_address' => 'student',
 
	       );
 
}
 

	
 
function default_instructions_html()
 
{
 
  return <<<EOF
 
<h2>Generic Instructions</h2>
 
<p>
 
  <tt>slate_permutate</tt> can be a useful tool for scheduling your next semester at the college you attend.
 
</p>
 
<ol>
 
  <li>Get in touch with your advisor and find out what courses you need to take next semester.</li>
 
  <li>Look up each course which your advisor specified in your college's course catalog. Note the different sectxions for each course..</li>
 
  <li>Enter each course into a <tt>slate_permutate</tt> schedule. For each course, add the sections listed in your school's course catalogue (at your discretion).</li>
 
  <li>Submit your list of courses and their sections. Let <tt>slate_permutate</tt> perform its magic.</li>
 
  <li>View all of the different permutations of your schedule and find a few that work for you.</li>
 
  <li>Print our your preferred schedule by selecting a schedule an choosing your User-Agent's print option.</li>
 
  <li>Wait until it's your turn to register and grab your preferred sections before they fill up!</li>
 
</ol>
 
EOF;
 
}
0 comments (0 inline, 0 general)