<?php

/*
    MWeather - A weather script written in PHP
    Copyright (C) 2000 Matt Wilson <matt@mattsscripts.co.uk>

    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
*/

echo "<!-- MWeather by Matt Wilson <matt@mattsscripts.co.uk>-->";

$mweatherDir = './';

// the config file
require "${mweatherDir}config.php";

if(!isset($region)){
        $region = $default_region;       // our default region
}

// just make sure =D
$region = strtoupper($region);

// just in case we're only running php3, which doesnt have an array shifting function
function array_myshift(&$a)
{
	// if the array is 0 elements in size then return false
	if(!sizeof($a)){
		return false;
	}

	// trim the first element and store it in $c
	$c = trim($a[0]);
	
	// for each other element (discarding the first) in $a store them in $b
	for($t=1; $t<sizeof($a); $t++){
		$b[] = $a[$t];
	}

	// store $b in $a
	$a = $b;
	
	// return the first element
	return $c;
}

// and another php4 only function
function my_inarray($s, $a){
	for($p=0; $p<sizeof($a); $p++){
		if($a[$p] == $s){
			return true;
		}
	}

	return false;
}

// one for hashes
function my_inhash($s, $a){
	if(!$a[$s]){
		return false;
	} else {
		return true;
	}
}

if($ctime = @filemtime($cache_dir."/".$region.".TXT")) {
	$curtime = time();
	if($curtime - $ctime < $cache_age) {
		print "\n<!-- Using cache'd METAR data -->";
		$metar_ = @file($cache_dir."/".$region.".TXT");
	}
}

if(!$metar_) {
	print "\n<!-- Download latest METAR data -->";
	if(($metar_ = @file("ftp://weather.noaa.gov/data/observations/metar/stations/$region.TXT")) == false){
		print "\n<!-- Unable to download latest METAR data, using cache'd data -->";
		if(($metar_ = @file($cache_dir."/".$region.".TXT")) == false) {
			print "\n<!-- No cache'd data found for particular location, showing no good :( -->";
			// the data was inaccessibly so goto the "no weather" page
			require "${mweatherDir}$noweather";
			exit();
		}
	} else {
		if($fd = @fopen($cache_dir."/".$region.".TXT", "w")) {
			for($l=0; $l<sizeof($metar_); $l++) { @fwrite($fd, $metar_[$l], strlen($metar_[$l])); }
			@fclose($fd);
			@touch($cache_dir."/".$region.".TXT");
		} else {
			print "\n<!-- Unable to store cache'd data on server, carrying on anyway -->";
		}
	}
}

// open the template file
if(($tmpl = @file("${mweatherDir}$template_main")) == false){
	require "${mweatherDir}$noweather";
	exit();
}

// this explodes the string passed in $e and strips out all the fully white space elements and returns an array
function strip_blank($e)
{
	// explode the array via " "
	$ar = explode(" ",$e);

	// construct an array
	$t_ = array();
	
	// step through the array and put the non-zero elements into the new array $t_
	for($t=0; $t<sizeof($ar); $t++){
		if(strlen($ar[$t])){
			$t_[] = $ar[$t];
		}
	}

	// return the array
	return $t_;
}

// *shrug* - I have absolutely no idea what this does ;)
// only joking, its quite simple really...
function temp_image($temp)
{
	global $sun_vhot;
	global $sun_hot;
	global $sun_med;
	global $sun_low;
	global $sun_vlow;
	global $sun_vvlow;

	if($temp > 40){
		return $sun_vhot;
	}
	
	if($temp > 30){
        	return $sun_hot;
	}
	
	if($temp > 20){
        	return $sun_med;
	}
	
	if($temp > 10){
        	return $sun_low;
	}
	
	if($temp > 0){
        	return $sun_vlow;
	}
	
	return $sun_vvlow;
}

// returns the wind direction as a string
function return_wind_dir($wind_dir)
{
	if(348 < $wind_dir || $wind_dir <= 11) { return "North"; }
	if(11 < $wind_dir && $wind_dir <= 33) { return "North North East"; }
	if(33 < $wind_dir && $wind_dir <= 57) { return "North East"; }
	if(57 < $wind_dir && $wind_dir <= 78){ return  "East North East"; }
	if(78 < $wind_dir && $wind_dir <= 102){ return "East"; }
	if(102 < $wind_dir && $wind_dir <= 123){ return "East South East"; }
	if(123 < $wind_dir && $wind_dir <= 157){ return "South East"; }
	if(157 < $wind_dir && $wind_dir <= 168){ return "South South East"; }
	if(168 < $wind_dir && $wind_dir <= 192){ return "South"; }
	if(192 < $wind_dir && $wind_dir <= 213){ return "South South West"; }
	if(213 < $wind_dir && $wind_dir <= 237){ return "South West"; }
	if(237 < $wind_dir && $wind_dir <= 258){ return "West South West"; }
	if(258 < $wind_dir && $wind_dir <= 282){ return "West"; }
	if(282 < $wind_dir && $wind_dir <= 303){ return "West North West"; }
	if(303 < $wind_dir && $wind_dir <= 327){ return "North West"; }
	if(327 < $wind_dir && $wind_dir <= 348){ return "North North West"; }

	// this should never happen, but just in case it doesn, return a readable string
	return "?Unknown?";
}

// this formats the wind information for us
function format_windinfo($wind_dir, $wind_speed, $wind_units)
{
	global $wind_format;

	if(!isset($wind_dir) || !isset($wind_speed) || !isset($wind_units)){
		return "No wind information";
	}

	$wind_info = str_replace("%S%", $wind_speed, $wind_format);
	$wind_info = str_replace("%U%", $wind_units, $wind_info);
	$wind_info = str_replace("%D%", return_wind_dir($wind_dir), $wind_info);
	return str_replace("%d%", $wind_dir, $wind_info);
}

// this attempts to retrieve the name of the place which the regioncode relates to
function getareaname()
{
	global $region;
	global $mweatherDir;

	// attempt to read the CODES file, if it can't be found, return an error
	if(($codes = @file("${mweatherDir}CODES")) == false){
		return "Missing Codes File - ${mweatherDir}CODES";
	}

	// step through each line of the codes file looking for the one we want
	for($tmp=0; $tmp<sizeof($codes); $tmp++){
		// does this line contain our code?
		$_o = strpos($codes[$tmp],$region);
		
		if ((string)$_o == ""){
			// no
			continue;
		}

		// yes! trim the name and return it... i'm doing it this way because of something i'm planning with the CODES file ;)
		$t = explode(" -> ",$codes[$tmp]);
		
		return trim($t[1]);
//		return trim(substr($codes[$tmp],$_o+8));
	}

	// if the region code cannot be found return Unknown
	return "Unknown";
}

// this allows the drop down menus
function do_drop_down()
{
	global $use_dropdown_menus;
	global $dropdown_area;

	$dropdown_area_ = strtolower($dropdown_area);

	if(!$use_dropdown_menus){
		// dont use drop down menus
		return "<!--- drop down turned off --->";
	}

	if(($codes = @file("dropdown.cfg")) == false){
		// cant find the config file, so simply dont use it
		return "<!--- dropdown.cfg file not found --->";
	}

	for($tmp=0; $tmp<sizeof($codes); $tmp++){
		$fc = substr($codes[$tmp],0,1);
		if($fc == "-"){
			// get the code
			$code = substr($codes[$tmp], 1, strlen($codes[$tmp])-2);

			// check to see if its the one we want
			if(trim(strtolower($code)) == trim($dropdown_area_)){
				// found it!
				break;
			}
		}
	}

	if(strtolower($code) != $dropdown_area_){
		// unknown region
		return "<!--- drop down region un-supported --->";
	}

	// begin the construction of the form code
	$formcode = "<form action='mweather.php' method=post>\n<select name=region>\n";

	// tmp counter
	$tmp++;

	// construct the form code (the rest of)
	while(substr($codes[$tmp],0,1) != "+"){
		// get the codes
		$stuff = explode(" -> ",$codes[$tmp]);
		$formcode .= "<option value=".trim($stuff[0]).">".$stuff[1]."</option>\n";
		$tmp++;
	}

	// finish off the form code
	$formcode .= "</select><input type=hidden name=dropdown_area value='".$dropdown_area."'><input type=submit value='Go!'></form>";

	// return the code for the form drop down menu
	return $formcode;
}

// this is for the formatting of the date
function updatedt($date, $month, $year, $time, &$ndate, &$ntime)
{
        global $date_format;
	global $time_format;
	global $time_offset;
	
        $_t = explode(":",$time);

	// this *might* work for UTC time
	$_t[0] += $time_offset;
	
	// convert the time
        $ndate = date($date_format,mktime($_t[0], $_t[1], 0, $month, $date, $year));
	$ntime = date($time_format,mktime($_t[0], $_t[1], 0, $month, $date, $year));
}

// the area name isn't set? well, try and get it from the CODES file
if(!isset($area_name) || !strlen($area_name)){
	$area_name = getareaname();
}

$tmpl = implode("",$tmpl);

// strip the EOLs from each line of the METAR file
for($t=0; $t<sizeof($metar_); $t++){
	$metar_[$t] = trim(str_replace("\n","",$metar_[$t]));
}

// implode the METAR file array so we have one long list of single-space seperated strings
$metar = implode(" ",strip_blank(implode(" ",$metar_)));

echo "<!-- metar codes = `$metar' -->\n";
$options = explode(" ",$metar);
$____ = explode("/",array_myshift($options));
$year = $____[0];
$month = $____[1];
$date = $____[2];
$time = array_myshift($options);

$_ = array_myshift($options);
if($_ != $region){	// the region, indicating an error in the data file
	echo "\n<!-- crashed checking region - reported as `$_' -->\n";
//	require "${mweatherDir}$noweather";
//	exit();
}

// another indication of an error in the data file
$check = array_myshift($options);
if($check != $date.str_replace(":","",$time)."Z"){
	echo "\n<!-- crashed checking date/time - reported as $check -->\n";
//	require "${mweatherDir}$noweather";
//	exit();
}

settype($year,"integer");
settype($month,"integer");
settype($date,"integer");

// before we start it, lets create a couple of useful reg exp sections

// construct a regular expression to match the start of a string to a precipitation type ;)
while(list($key, $var) = each($precip_types)){
	$teg[] = $key;
}
$regu = implode("|", $teg);

// and one for clouds
while(list($key, $var) = each($cloud_types)){
	$ceg[] = $key;
}
$cloud_reg = implode("|", $ceg);

// ok, on with the show!
while(($_op = array_myshift($options)) != false){

	// just in case a zero-length option got through ;) this should not happen though
	if(!strlen($_op)){
		continue;
	}

	// is this likely to be wind? I reckon this can only happen once, so i'm going to make it not be checked more than once =P
	if($dealt_with_wind == false){
		if(ereg("(MPS)$", $_op) || ereg("(KT)$", $_op)){
			print "<!-- WIND FOUND => \$_op = `$_op' -->\n";
			$dealt_with_wind = true;
			$wind_dir = substr($_op,0,3)%360;
			settype($wind_dir,"integer");
			$wind_speed = substr($_op,3,2);
			settype($wind_speed,"integer");
			$wind_units = substr($_op,5);

			if($wind_units == "KT"){
				$wind_units = " knots";
			} else { /* this means the `G' or gusts is present and it needs to be parsed differently */
				$gust_speed = substr($_op, 6, 2);
				settype($gust_speed, "integer");
				$wind_units = substr($_op, 8);
				if($wind_units == "KT"){
					$wind_units = "knots sustained, gusting to ".$gust_speed;
				}
			}
			
			continue;
		}
	}

// cloud info?
	$_ = substr($_op,0,3);

	if(ereg("^(".$cloud_reg.")", $_)){
		print "<!-- CLOUD INFO FOUND => \$_op = `$_op' -->\n";
		$cloud_type[] = $_;
		
	//	if($_ == "CLR"){
	//		// if the cloud type is CLR then set the height to 12000 feet
	//		$cloud_height[] = 120;
	//	} else{
			$tch = substr($_op,3,3);
			if(!$tch){
				$cloud_height[] = 120;
			} else {
				$cloud_height[] = $tch;
			}
			// otherwise we want the data
			settype($cloud_height[sizeof($cloud_height)-1],"integer");
			$cloud_height[sizeof($cloud_height)-1] *= 100;
	//	}
		
		// convert the cloud height to metar height
		$cloud_height_metar[] = $cloud_height[sizeof($cloud_height)-1]/3.281027104;
		
		continue;
        }

// temperature info? - no point in doing it twice, this one is a bitch mind you...
	if($dealt_with_temperature == false){
		if(ereg("^(M?)([0-9]{2})/(M?)([0-9]{2})$", $_op)){
			print "<!-- TEMP INFO FOUND => \$_op = `$_op' -->\n";
			
			// AFAIK the M at the beginning refers to (M)inus and hence needs to be there...
			$_op = str_replace("M", "-", $_op);
			
			// calculations and stuff
			$dealt_with_temperature = true;
			$tmps = explode("/", $_op);
			$temp = $tmps[0];
			
			print "<!-- \$temp = $temp -->\n";
			
			@settype($temp,"integer");
			$temp_dewpoint = $tmps[1];
			print "<!-- \$temp_dewpoint = $temp_dewpoint -->\n";
			@settype($temp_dewpoint,"integer");
                        $temp_f = @round(($temp*9/5)+32);
                        $temp_dewpoint_f = ($temp_dewpoint*9/5)+32;

			// thanks to Rick MacDougall for this !
			$Td = 273.15 + $temp_dewpoint;
			$T  = 273.15 + $temp;
			$e  = 6.11 * exp(5417.118093 * (0.003660992 - (1/$Td)));
			$es  = 6.11 * exp(5417.118093 * (0.003660992 - (1/$T)));
			$humidity = ($e/$es) * 100;
			@settype($humidity,"integer");
			// end humidity calculating code :P
			
			continue;
		}
	}

	// check to see whether this is likely to be a precipitation info bit
	if(ereg("^(\-?)(".$regu.")", $_op) && eregi("^(\-?)([a-z]+)$",$_op)){
		print "<!-- PRECIP INFO FOUND => \$_op = `$_op' -->\n";
		// it most likely is! so lets parse as though it is, start by getting rid of that annoying "-" which sometimes appears at the beginning
		$_op = str_replace("-", "", $_op);

		// store the precip info at the end of $precip array
		$precip[] = substr($_op, 0, 2);

		// if there is some more info on this precipitation then we might as well get it
		if(strlen($_op) > 2){
			$precip_descrip[] = substr($_op, 2);
		} else {
			$precip_descrip[] = "";
		}

		continue;
	}
	
	// precip intensity info, should only appear once!
	if($got_precip_intensity == false){
		if(ereg("^([0-9]){4}$",$_op)){
			print "<!-- PRECIP_INTENSITY FOUND => \$_op = `$_op' -->\n";
			settype($_op, "string");
			$precip_intensity[] = substr($_op, 0, 1);
			$precip_intensity[] = substr($_op, 1, 1);
			$precip_intensity[] = substr($_op, 2, 1);
			$precip_intensity[] = substr($_op, 3, 1);
			$got_precip_intensity = true;
			continue;
		}
	}
}

// determine which pictures to use  

$img_temp = temp_image($temp);

// the below two pieces of code have both been used to dynamically alter the cloud picture, but to be honest, lets just have the first cloud type as our pictue :P
if(!sizeof($cloud_type)){
	$cloud_img = $unknowninfo;
} else {
	$cloud_img = $cloud_type[0];
}

/*
// determine which cloud picture to use, note that the cloud_type array keys are sorted in terms of density of cloud ;)
while($key = key($cloud_types)){
	print "<!-- \$key = \$var -->\n";
	if(isset($cloud_types[$key])){
//	if(my_inhash($key, $cloud_types)){
		$cloud_img = $key;
		break;
	}
}
*/

/*
for($l=0; $l<sizeof($cloud_type); $l++){
	if($cloud_type[$l] == "OVC"){
		$cloud_img = "OVC";
		break;
	}
	elseif($cloud_type[$l] == "BKN" && $cloud_img != "OVC") { $cloud_img = "BKN"; }
	elseif($cloud_type[$l] == "SCT" && $cloud_img != "OVC" && $cloud_img != "BKN") { $cloud_img = "SCT"; }
	elseif($cloud_type[$l] == "FEW" && $cloud_img != "OVC" && $cloud_img != "BKN" && $cloud_img != "SCT") { $cloud_img = "FEW"; }
	else
		$cloud_img = "SKC";
}
*/

if($use_head_and_foot_templates){
	require "${mweatherDir}$template_header";
}

$wind_info = format_windinfo($wind_dir, $wind_speed, $wind_units);

if(sizeof($cloud_type)){
	for($l=0; $l<sizeof($cloud_type); $l++){
		$cloud_info = sprintf("%s%s&nbsp;@&nbsp;%d&nbsp;feet&nbsp(%d&nbsp;metar)<br>",$cloud_info,$cloud_types[$cloud_type[$l]],$cloud_height[$l],$cloud_height_metar[$l]);
	}
}
else{
	$cloud_info = "Unknown";
}

if(sizeof($precip)){
	for($l=0; $l<sizeof($precip); $l++){
		if($got_precip_intensity == true){
			$precip_info = sprintf("%s%s&nbsp;(%s)",$precip_info,$precip_types[$precip[$l]],$precip_intensities[$precip_intensity[$l]]);
		} else {
	              	$precip_info = sprintf("%s%s",$precip_info,$precip_types[$precip[$l]]);
		}

		if(strlen($precip_descrip[$l])){
			$precip_info = sprintf("%s&nbsp;(%s)",$precip_info,$precip_types[$precip_descrip[$l]]);
		}

//		$precip_info = sprintf("%s)<br>",$precip_info);
		$precip_info = sprintf("%s<br>",$precip_info);
	}
	$precip_img = $precip_images[$precip[0]];
}
else{
	$precip_info = "None";
	$precip_img = $cloud_images["CLR"];
}

updatedt($date, $month, $year, $time, $ndate, $ntime);

// perform all the replacements in the html page
$tmpl = str_replace("[>AREA_NAME<]", $area_name, $tmpl);
$tmpl = str_replace("[>FDATE<]", $ndate, $tmpl);
$tmpl = str_replace("[>TIME<]", $ntime, $tmpl);
$tmpl = str_replace("[>TEMP_C<]", $temp, $tmpl);
$tmpl = str_replace("[>TEMP_F<]", $temp_f, $tmpl);
$tmpl = str_replace("[>HUMIDITY<]", $humidity, $tmpl);
$tmpl = str_replace("[>TEMP_IMG<]", $imagePath.$img_temp, $tmpl);
$tmpl = str_replace("[>WIND_INFO<]", $wind_info, $tmpl);
$tmpl = str_replace("[>CLOUD_INFO<]", $cloud_info, $tmpl);
$tmpl = str_replace("[>CLOUD_IMG<]", $imagePath.$cloud_images[$cloud_img], $tmpl);
$tmpl = str_replace("[>PRECIP_INFO<]", $precip_info, $tmpl);
$tmpl = str_replace("[>PRECIP_IMG<]", $imagePath.$precip_img, $tmpl);
$tmpl = str_replace("[>REGION_DD<]", do_drop_down(), $tmpl);

// show the template
echo $tmpl;

if($use_head_and_foot_templates){
	require "${mweatherDir}$template_footer";
}
?>
