view index.php @ 59:aa201ddd33dd

Cleaned up, v2.0 beta.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 24 Oct 2012 01:31:10 +0300
parents 16aea8e5cb71
children cdc04572800c
line wrap: on
line source

<?php
//
// Yes, this is horrible. :|
//
$pageCharset = "utf-8";
$internalCharset = "utf-8";
$luokkaDefault = "TTE9SNO";
$classFile = "luokat.txt";
$cacheFile = "coursecache.txt";
$baseURI = "http://tnsp.org/luk2/";
//$infoURI = "http://www.oamk.fi/opiskelijalle/rakenne/opinto-opas/koulutusohjelmat/?sivu=oj&kieli=FI&opas=2010-2011&vuosi=10S11K&koodi1=";
$infoURI = "http://www.oamk.fi/opiskelijalle/rakenne/opinto-opas/koulutusohjelmat/?sivu=oj&kieli=FI&koodi1=";
$dayNames = array("Maanantai", "Tiistai", "Keskiviikko", "Torstai", "Perjantai", "Lauantai", "Sunnuntai");

$pageCSSData = array("cookie" => "lukcss", "prefix" => $baseURI."luk");
$pageCSSAlts = array("blue" => "1", "old" => "2", "purple" => "3");

// Include framework
require "mcommon.inc.php";
require "merrors.inc.php";


// Helper functions
function lukChEntities($str)
{
  global $internalCharset;
//  return $str;
  return htmlentities($str, ENT_NOQUOTES, $internalCharset);
}

function lukCheckClassID(&$id)
{
  global $luokkaDefault;
  if (preg_match("#^([A-Z]{3}\d[A-Za-z0-9_]{1,6}|ccr|Ryh_[A-Z]{3}\d[A-Za-z0-9_]{1,6})$#", $id, $m)) {
    $id = $m[1];
    return TRUE;
  } else {
    errorMsg("Virhe! Luokan täytyy olla muotoa <b>XXXnXXX</b>, käytetään vakioarvoa <b>".$luokkaDefault."</b>.");
    $id = $luokkaDefault;
    return FALSE;
  }
}


function lukGetDayFromTimestamp($stamp)
{
  $info = getdate($stamp);
  $day = $info["wday"];
  return ($day > 0) ? $day - 1 : $day + 6;
}


function lukGetHourStamp($stamp)
{
  return date("H:i", mktime(0, 0, $stamp, 0, 0, 0));
}


function lukGetHourStr($hour)
{
  global $classHourTimes;
  if (isset($classHourTimes[$hour]))
  {
    return
      "<br />".
      lukGetHourStamp($classHourTimes[$hour]["start"]).
      " - ".
      lukGetHourStamp($classHourTimes[$hour]["end"]).
      "<br /><br />";
  }
  else
    return "ERROR";
}


function lukMatchCourse($id)
{
  global $cache, $infoURI, $cacheDirty, $internalCharset;

  // Check if course exists in cache
  if (!isset($cache[$id]))
  {
    // Not cached, try to fetch data
    $cacheDirty = TRUE;
    $data = @file_get_contents($infoURI.$id);
    if ($data !== FALSE)
    {
      $data = iconv("iso-8859-1", $internalCharset, $data);
      if (preg_match("#<td class=\"smallheadercell\"><strong>(.+?)\s+(\d+)\s*op\s*</strong></td>#", $data, $m))
      {
        // Add data to cache
        $cache[$id] = array("desc" => $m[1], "op" => intval($m[2]));
      }
    }
  }
  
  if (isset($cache[$id]))
  {
    return "<a target=\"_blank\" title=\"".lukChEntities($id." - ".$cache[$id]["op"]." op").
    "\" href=\"".lukChEntities($infoURI.$id)."\">".lukChEntities($cache[$id]["desc"])."</a>";
  }
  else
    return lukChEntities($id);
}


function lukGetClassInfo($isSplit, $data)
{
  if ($isSplit)
  {
    $out = "<table>".
    "<tr><td>".lukMatchCourse($data[0])."</td><td>".lukMatchCourse($data[1])."</td></tr>";

    for ($i = 2; $i < count($data); $i += 2)
    {
      $out .= "<tr><td>".lukChEntities($data[$i])."</td><td>".
        (isset($data[$i+1]) ? lukChEntities($data[$i+1]) : "")."</td></tr>";
    }
    
    return $out."</table>";
  }
  else
  {
    $out = lukMatchCourse($data[0])."<br />";

    for ($i = 1; $i < count($data); $i++)
    {
      $out .= lukChEntities($data[$i])."<br />";
    }

    return $out;
  }
}


function lukGetClassInfoData($id)
{
  global $classInfo;

  if (isset($id))
  {
    if ($id >= 0 && isset($classInfo[$id]))
    {
      $i = $classInfo[$id];
      $isSplit = preg_match("/^[A-Z]\d{6}$/", $i["data"][1]);
      return lukGetClassInfo($isSplit, $i["data"]);
    }
    else
      return "<p>Ei tunteja.</p>";
  }
  else
    return "<p>Ei mitään.</p>";
}


function lukFindClass($day, $hour)
{
  global $classHourDefs, $classDayTable;
  if (isset($classDayTable[$day]))
  {
    foreach ($classDayTable[$day] as $id)
    {
      if ($hour >= $classHourDefs[$id]["start"] && 
          $hour <  $classHourDefs[$id]["start"] + $classHourDefs[$id]["hours"])
        return $id;
    }
  }
  return 0;
}


// Check for mini-info mode
$miniMode = isset($_GET["nyt"]);

// Check given parameters
if (isset($_GET["luokka"]))
{
  $luokka = $_GET["luokka"];
  if (lukCheckClassID($luokka) && !$miniMode)
  {
    setcookie("lukluokka", $luokka, time() + 365*24*60*60); // expire in a year
  }
}
else
if (isset($_COOKIE["lukluokka"]))
{
  $luokka = $_COOKIE["lukluokka"];
  lukCheckClassID($luokka);
}
else
{
  errorMsg("Luokkaa ei asetettu, käytetään vakioarvoa <b>".$luokkaDefault."</b>.");
  $luokka = $luokkaDefault;
}


if (isset($_GET["next"]))
{
  $nextPeriod = TRUE;
  $dataFile = "cache-next/".$luokka.".data";
}
else
{
  $nextPeriod = FALSE;
  $dataFile = "cache/".$luokka.".data";
}


// Global cache for course data
$cache = array();
$cacheDirty = FALSE;

// Try to read cachefile, if we can get file lock on it
$fp = @fopen($cacheFile, "rb");
if ($fp)
{
  if (flock($fp, LOCK_SH))
  {
    require($cacheFile);
    flock($fp, LOCK_UN);
  }
  fclose($fp);
}


// Read classfile
$classes = array();
$fp = @fopen($classFile, "rb");
if ($fp)
{
  if (flock($fp, LOCK_SH))
  {
    while (!feof($fp))
    {
      $str = trim(fgets($fp, 128));
      if (strlen($str) > 2 && $str[0] != "#")
        $classes[] = $str;
    }
    flock($fp, LOCK_UN);
  }
  fclose($fp);
}
else
{
  errorMsg("Luokkien listaa ei löytynyt. Kokeile ladata sivu uudelleen hetken kuluttua.");
}


if (!file_exists($dataFile))
{
  errorMsg("Luokan ".lukChEntities($luokka)." tietoja ei löytynyt! ".
  "Jos luokkakoodi on uusi, ilmestyy se järjestelmään seuraavan ".
  "päivityksen aikana. Luokkatiedot päivitetään kerran viikossa.");
  $haveData = FALSE;
}
else
{
  require($dataFile);
  $haveData = isset($classInfo);
}


function lukNormalTimeTable()
{
  global $classInfo, $classHourDefs, $dayNames, $classHourTimes;
  
//  $currStamp = time() + 9 * 60 * 60 + 18 * 60;
  $currStamp = time();
  $currTime = $currStamp - mktime(0, 0, 0);
  $currDay = lukGetDayFromTimestamp($currStamp);
  
  // Create the timetable table
  $out =
  "<p>".join("; ", $classInfo["general"])."</p>\n".
  "<div>Viikossa yhteensä <b>".$classInfo["totalHours"]."</b> tuntia.</div>\n".
  "<table class=\"timetable\">".
  " <tr>\n  <th></th>\n";
  $cellWidth = 100 / $classInfo["maxDays"];
  if ($cellWidth > 25) $cellWidth = 25;
  for ($day = 0; $day < $classInfo["maxDays"]; $day++)
  {
    $out .=  "  <th style=\"width: ".$cellWidth."%;\" class=\"days\">".$dayNames[$day]."</th>\n";
  }
  $out .= " </tr>\n";

  for ($hour = $classInfo["firstHour"]; $hour < $classInfo["lastHour"]; $hour++)
  {
    $out .= " <tr>\n".
    "  <th class=\"hours\">".lukGetHourStr($hour)."</th>\n";
    for ($day = 0; $day < $classInfo["maxDays"]; $day++)
    {
      $id = lukFindClass($day, $hour);
      if ($id > 0)
      {
        $class = &$classHourDefs[$id];
        if (!isset($class["set"]))
        {
          $class["set"] = TRUE;

          $isSplit = preg_match("/^[A-Z]\d{6}$/", $class["data"][1]);

          $isActive = $day == $currDay &&
                      $currTime >= $classHourTimes[$class["start"]]["start"] &&
                      $currTime <  $classHourTimes[$class["start"] + $class["hours"] - 1]["end"];

          $out .= "  <td rowspan=\"".$class["hours"].
          "\" class=\"".($class["grouped"] ? "clgrouped" : ($isActive ? "clactive" : "clnormal"))."\">";

//          if ($isActive)
//            $out .= sprintf("%d : %d <> %d, %d -- ", $day, $currTime, $classHourTimes[$class["start"]]["start"], $classHourTimes[$class["start"] + $class["hours"] - 1]["end"]);
          
          $out .=
          lukGetClassInfo($isSplit, $class["data"]).
          "</td>\n";
        }
      }
      else
      {
        $out .= "  <td class=\"clnothing\"></td>\n";
      }
    }
    $out .= " </tr>\n";
  }

  return $out."</table>\n";
}


//
//
//
$pageTitle = $haveData ? $luokka." / ".join("; ", $classInfo["info"]) : $luokka;
printPageHeader($pageTitle);

echo "<form id=\"controls\" action=\"".$baseURI."\" method=\"get\">
 <table>
  <tr>
   <th>
    <select name=\"luokka\">
";

foreach ($classes as $class) {
  echo "     <option ".($luokka == $class ? "selected=\"selected\" " : "")."value=\"".$class."\">".lukChEntities($class)."</option>\n";
}
echo 
"    </select>
   </th>
   <th><input class=\"submit\" type=\"submit\" value=\" Vaihda \" /></th>
   <th><a href=\"".$baseURI."?luokka=".$luokka;

if ($miniMode)
  echo "\">Normaali";
else
  echo "&amp;nyt\">Mini-info";

echo "</a></th>
   <th><a href=\"http://www.oamk.fi/tyojarjestykset/otek/luokat/OR_".$luokka.".htm\">Alkuperäinen</a></th>

   <th><a href=\"".$baseURI.($nextPeriod ? "" : "?next")."\">".($nextPeriod ? "Nykyinen" : "Seuraava")." periodi</a></th>
  </tr>
 </table>
</form>
";

echo "<h1>".$pageTitle."</h1>\n";

// Show error messages
if ($errorSet)
{
  echo "<ul>\n";
  foreach ($errorMsgs as $msg)
    echo "<li>$msg</li>\n";
  echo "</ul>\n";
}

if ($haveData)
{
  echo lukNormalTimeTable();
}

echo "<div id=\"footer\">
Yhteydenotot <b>ccr @ IRCNet</b> tai <b>ccr at tnsp dot org</b>. En vastaa mahdollisista virheistä tiedoissa!
</div>
<div id=\"csssel\">
<div id=\"ctitle\">Lukkari v2.0 beta</div>
Style: ";
foreach ($pageCSSAlts as $name => $id)
  echo "<a href=\"?css=".$id."\">".$name."</a>";
echo "
</div>
";
printPageFooter();


// Dump the course data cache, but only if it has changed
if ($cacheDirty) {
  // Create string containing the data
  $str = "<?\n\$cache = array(\n";
  foreach ($cache as $id => $data) {
    $str .= "  \"".addslashes($id)."\" => array(\"desc\" => \"".
            addslashes($data["desc"])."\", \"op\" => ".$data["op"]."),\n";
  }
  $str .= ");\n?>";
  
  // Use locking to prevent concurrent access and dump data
  if (file_put_contents($cacheFile, $str, LOCK_EX) === FALSE) {
    // Can't do much anything here ..
  }
}

?>