<?php
/*
Copyright (C) 2004 Paul Marks
http://www.pmarks.net/
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
function weekWrap($t)
{
return ($t + 10080) % 10080;
}
function timeInRange($time, $min, $max)
{
// returns true if MIN <= TIME < MAX, wrapped through 0-10079
$time = weekWrap($time);
$min = weekWrap($min);
$max = weekWrap($max);
if ($min < $max)
{
return ($time >= $min && $time < $max);
}
elseif ($min > $max)
{
return ($time >= $min || $time < $max);
}
return false;
}
function timeConvert($time)
{
list($h,$m) = explode(':', $time);
$ampm = strtolower(substr($time,-2));
if ($ampm == 'am' && $h == 12)
{
$h = 0;
}
elseif ($ampm == 'pm' && $h != 12)
{
$h += 12;
}
return ($h * 60 + (int)$m); // return number of minutes after midnight
}
function startElement($parser, $name, $attr)
{
global $curHallData, $curBlockData;
$GLOBALS['curElement'] = $name;
switch ($name)
{
case 'HALL':
$curHallData = array('hallid'=>$attr['ID'], 'hallname'=>'', 'x1'=>0, 'y1'=>0, 'x2'=>0, 'y2'=>0);
break;
case 'TIMEBLK':
$GLOBALS['inblock'] = true;
$curBlockData = array('name'=>'', 'type'=>strtolower($attr['TYPE']), 'days'=>array(), 'open'=>0, 'close'=>0);
break;
}
}
function characterData($parser, $data)
{
global $curHallData, $curBlockData;
switch ($GLOBALS['curElement'])
{
case 'NAME':
if ($GLOBALS['inblock'])
$curBlockData['name'] = $data;
else
$curHallData['name'] = $data;
break;
case 'X1':
$curHallData['x1'] = $data;
break;
case 'Y1':
$curHallData['y1'] = $data;
break;
case 'X2':
$curHallData['x2'] = $data;
break;
case 'Y2':
$curHallData['y2'] = $data;
break;
case 'OPEN':
$curBlockData['open'] = timeConvert($data);
break;
case 'CLOSE':
$curBlockData['close'] = timeConvert($data);
break;
case 'DAY':
$curBlockData['days'][] = array_search(strtolower(substr($data,0,3)),array('sun','mon','tue','wed','thu','fri','sat'));
break;
}
}
function endElement($parser, $name)
{
$GLOBALS['curElement'] = "";
if ($name == 'TIMEBLK')
{
global $curBlockData, $curHallData, $allBlocks, $wkTime, $mode, $selBlock;
$GLOBALS['inblock'] = false;
if ($mode == $curBlockData['type'])
{
$state = 0;
foreach ($curBlockData['days'] as $day)
{
$wkOpen = $day*1440 + $curBlockData['open'];
$wkClose = $day*1440 + $curBlockData['close'];
if ($wkClose <= $wkOpen) $wkClose += 1440;
$wkCloseSoon = $wkClose - 15;
if ($wkCloseSoon < $wkOpen) $wkCloseSoon = $wkOpen;
if (timeInRange($wkTime, $wkOpen-30, $wkOpen)) $state = 1; // opening soon
elseif (timeInRange($wkTime, $wkOpen, $wkCloseSoon)) $state = 2; // open
elseif (timeInRange($wkTime, $wkCloseSoon, $wkClose)) $state = 3; // closing soon
if ($state)
{
if (@$_GET['id'] == $curHallData['hallid'])
{
$selBlock = array('hallid'=>$curHallData['hallid'], 'name'=>$curHallData['name'], 'blockname'=>$curBlockData['name'], 'open'=>$wkOpen, 'close'=>$wkClose, 'state'=>$state);
}
$allBlocks[] = array_merge($curHallData, array('state'=>$state));
break;
}
}
}
}
}
function parseFile($filename)
{
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, 'startElement','endElement');
xml_set_character_data_handler($xml_parser, 'characterData');
$fp = fopen($filename,'r');
if (!$fp) exit ("Can't open dining hall information file.");
while ($data = fread($fp,4096))
{
if (!xml_parse($xml_parser, $data, feof($fp)))
{
exit(sprintf("XML error at line %d column %d ", xml_get_current_line_number($xml_parser), xml_get_current_column_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
}
function jsArray($varname,$items)
{
if (count($items) == 1)
{
echo "var $varname = new Array(1); " . $varname . "[0] = " . $items[0] . ";\n";
}
else
{
echo "var $varname = new Array(" . implode(',',$items) . ");\n";
}
}
function remainTime($time)
{
$time = weekWrap($time);
$out = '';
$h = floor($time / 60);
$m = $time % 60;
if ($h == 1)
$out .= '1 Hour';
elseif ($h > 1)
$out .= $h . ' Hours';
if ($h > 0 && $m > 0)
$out .= ', ';
if ($m == 1)
$out .= '1 Minute';
elseif ($m > 1 || $h = 0)
$out .= $m . ' Minutes';
return $out;
}
function getMenu($id)
{
$date = date('n/j/Y', $GLOBALS['utc_time']);
$cfile = 'menu_cache/' . $id;
$menu_html = '';
$menuf = fopen($cfile, 'r');
if ($menuf && $date == trim(fgets($menuf)))
{
$menu_html = fgets($menuf, 16384);
fclose($menuf);
}
else
{
fclose($menuf);
// 2019-03-02 -- Put this fetch out of its misery.
//$menuwww = @fopen('http://www.housing.purdue.edu/menus/menu.aspx?hallID=' . $id . '&date=' . $date, 'r');
$menu_html = "";
if ($menuwww)
{
while ($line = fgets($menuwww, 65536))
{
if (strstr($line, MENU_DIVIDER))
{
$menu_html .= trim($line);
}
}
fclose($menuwww);
if ($menu_html)
{
$menuf = fopen($cfile, 'w');
fwrite($menuf, "$date\n$menu_html");
fclose($menuf);
}
}
else
{
echo '<div style="color:red; font-weight:bold;">Error Opening HFS Menu Page!</div>';
}
}
return $menu_html;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Purdue's time zone.
date_default_timezone_set("America/New_York");
define ('MENU_DIVIDER', '<div id="mealStation" class="meal">');
$mode = @$_GET['mode'];
if ($mode != 'dining' && $mode != 'other') $mode = 'dining';
$curElement = "";
$inblock = false;
$map_file = 'map.png';
$menu_url = "";
$menu_types = array('lunch'=>0, 'dinner'=>0);
$menuf = null;
$curHallData = array();
$curBlockData = array();
$allBlocks = array();
$selBlock = null;
srand((double)microtime() * 1000000);
if (@$_GET['time'])
{
$utc_time = $_GET['time'];
}
else
{
$utc_time = time();
}
$t = getdate($utc_time);
$wkTime = $t['wday']*1440 + $t['hours']*60 + $t['minutes'];
parseFile('halldata.xml');
$blockCount = count($allBlocks);
$fadeOffsets = array();
$colorList = array();
for ($i=0; $i<$blockCount; $i++)
{
$fadeOffsets[$i] = $i;
$colorList[$i] = $allBlocks[$i]['state'];
}
shuffle($fadeOffsets);
?>
<html>
<head>
<title>Purdue Findfood</title>
<meta name="Description" content="See a live map of which Purdue University dining halls are currently open, and what's on their menus.">
<meta http-equiv="refresh" content="<?=61-date('s')?>">
<style type="text/css">
<!--
#container ul {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px; margin: 0 75px 0 75px;
padding: 0 0 0 0;
text-align: center;
margin: 0 0 0 0; /*removes indent IE and Opera*/
padding: 0 0 0 0; /*removes indent Mozilla and NN7*/
list-style-type: none; /*turns off display of bullet*/
}
#mealStation {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px; font-weight: bold;
text-transform: uppercase;
color: #000;
background-color: #F5E0AF;
text-align: center;
padding: 3px;
margin: 20px 0px 5px 0px;
}
.menuBox {
background-color: #FEFAF2;
margin: 30px 0px 0px 5px;
}
.menuHeader {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-weight: bold;
margin: 0px 5px 0px 5px;
}
.footLink {
color: #FFFFFF;
text-decoration: none;
}
.menuLink {
color: #000000;
text-decoration: underline;
}
-->
</style>
<script language="JavaScript">
var angle = 0;
var twoPi = Math.PI * 2;
var hexChars = "0123456789ABCDEF";
<?php jsArray('color',$colorList); ?>
<?php jsArray('offset',$fadeOffsets); ?>
var total = <?=$blockCount?>;
function makeColor(col, brt)
{
var hex = hexChars.charAt(Math.floor(brt/16)) + hexChars.charAt(brt % 16);
switch(col)
{
case 1: return('#0000'+hex);
case 2: return('#00'+hex+'00');
case 3: return('#'+hex+'0000');
}
}
function changeColor()
{
angle += 0.3;
if (angle > twoPi) angle -= twoPi;
for (var i=0; i<total; i++)
document.getElementById('hall'+i).style.borderColor = makeColor(color[i], Math.round(48 * Math.sin(angle + offset[i]*twoPi/total) + 207));
}
</script>
</head>
<body>
<table><tr>
<td valign="top">
<table border="0" cellpadding="0" cellspacing="0">
<tr><td><img src="header.png" alt="Purdue Findfood - Created by Paul Marks"></td></tr>
<tr><td><table width="100%" border="0" cellpadding="5" cellspacing="0">
<tr><td bgcolor="#F5E0AF"><font face="Arial, Helvetica, sans-serif">
<?php
if ($selBlock)
{
if ($mode == 'dining')
{
$menu_mealname = $selBlock['blockname'];
$menu_hallname = $selBlock['name'];
foreach (array_keys($menu_types) as $key)
{
if (strpos(strtolower($menu_mealname), $key) !== FALSE)
$menu_types[$key] = 1;
}
$menu_id = $selBlock['hallid'];
$menu_url = 'http://www.housing.purdue.edu/menus/menu.aspx?hallID=' . $menu_id . '&date=' . date('n/j/Y', $utc_time);
}
?>
<strong>Hall:</strong> <?=$selBlock['name']?> - <?=$selBlock['blockname']?><br>
<strong>Time:</strong> <?=gmdate('g:ia',$selBlock['open']*60)?> - <?=gmdate('g:ia',$selBlock['close']*60)?><br>
<?php
if ($selBlock['state'] == 1)
{
echo 'Opens in ' . remainTime($selBlock['open'] - $wkTime);
}
else
{
echo 'Closes in ' . remainTime($selBlock['close'] - $wkTime);
}
echo "<br>\n";
}
elseif ($blockCount)
{
echo "<center>Click a hall below for details.</center>\n";
}
else
{
echo "<center>No halls of the selected type are open now.</center>\n";
$map_file = $mode . '_closed.png';
}
?>
</font></td></tr>
</table></td></tr>
<tr><td>
<div style="position:relative"><img src="<?=$map_file?>" width="500" height="523"><?php
$brdColor = array(1=>'0000FF',2=>'00FF00',3=>'FF0000');
$selBlock = 0;
for ($i=0; $i<$blockCount; $i++)
{
$b = $allBlocks[$i];
?><a href="?mode=<?=$mode?>&id=<?=$b['hallid']?>" title="<?=$b['name']?>"><img src="spacer.gif" alt="<?=$b['name']?>" id="hall<?=$i?>" width="<?=$b['x2']-$b['x1']-3?>" height="<?=$b['y2']-$b['y1']-3?>" border="3" style="position:absolute; left:<?=$b['x1']-1?>; top:<?=$b['y1']-1?>; border-color:#<?=$brdColor[$b['state']]?>;"></a><?php
}
?></div>
<script language="JavaScript">
setInterval('changeColor()', 75);
</script>
</td></tr>
<tr><td>
<table width="100%" border="0" cellpadding="5" cellspacing="0" bgcolor="#000000">
<tr>
<td align="left" valign="top"><font color="#FFFFFF" size="-1" face="Courier New, Courier, mono"><?=gmdate('l g:ia',$wkTime*60+259200)?></font></td>
<td align="right" valign="top"><font color="#FFFFFF" size="-1" face="Arial, Helvetica, sans-serif"><?php
if ($mode == 'dining')
echo '<font color="#FFFF00"><strong>Dining</strong></font>';
else
echo '<a href="?mode=dining" class="footLink">Dining</a>';
echo ' | ';
if ($mode == 'other')
echo '<font color="#FFFF00"><strong>Take-out</strong></font>';
else
echo '<a href="?mode=other" class="footLink">Take-out</a>';
?></font></td>
</tr>
</table>
</td></tr>
</table>
<br>
<a href="source.php">PHP Source Code</a>
</td>
<td valign="top" align="center">
<?php
if ($menu_url) {
?>
<div class="menuBox">
<span class="menuHeader"><?=$menu_mealname?> Menu For <a class="menuLink" href="<?=$menu_url?>"><?=$menu_hallname?></a>:</span>
<?php
$menu_html = '';
$items = explode(MENU_DIVIDER, getMenu($menu_id)); // split up line based on the div tags
foreach ($items as $item)
{
foreach ($menu_types as $key=>$value)
{
if ($value && strtolower(substr($item,0,strlen($key))) == $key)
{
$menu_html .= MENU_DIVIDER . $item;
break;
}
}
}
if ($menu_html)
echo $menu_html;
else
echo '<br><br><Menu Not Available>';
if ($menuf) fclose($menuf);
echo '</div>';
}
else
{
echo '<br><br><a href="http://www.mozilla.org/products/firefox/"><img src="firefox.png" img alt="Get Firefox!" title="Get Firefox!" border="0"></a>';
}
echo '</td>';
?>
</table>
</body>
</html>