<?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>&lt;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>