All pastes #2074396 Raw Edit

Miscellany

public php v1 · immutable
#2074396 ·published 2011-06-04 01:43 UTC
rendered paste body
<?phperror_reporting(E_ALL);libxml_use_internal_errors(true);// ********************* //// ***** FUNCTIONS ***** //// ********************* //class BDWeather {	// Extract a time-layout structure from the overall document ($X) for a	// given $Element.  Basically, $Element has a time-layout attribute.  The	// value of that attribute specifies a time-layout element to use for	// mapping the values in the element to a series of timestamps.	public static function getLayout($X, $Element) {		$layout = $Element->attributes()->{"time-layout"};		$times = self::getPath($X, "data/time-layout[layout-key='{$layout}']");		if (count($times) == 0) throw new Exception("Could not find time layout [{$layout}]");		return current($times);	}	// Do the basic rest call to get the weather data we want.	public static function restCall($zip) {		$params = array(			"whichClient" => "NDFDgenMultiZipCode",			"zipCodeList" => $zip,			"product" => "time-series",			"temp" => "temp",			"wspd" => "wspd",			"sky" => "sky",			"precipa_r" => "precipa_r",		);		$uri_base = "http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdXMLclient.php";		$uri = "{$uri_base}?" . http_build_query($params);		$result = file_get_contents($uri);		try {			$X = new SimpleXMLElement($result);		} catch (Exception $E) {			// Add the result into the exception and rethrow it, so we can see what the bad XML was later.			$E->result = $result;			throw $E;		}		return $X;	}	// Given a SimpleXMLElement object, and an XPath path, do the search, and deal with possible error conditions.	public static function getPath($X, $path) {		if (!($X instanceof SimpleXMLElement)) throw new Exception("X is not a SimpleXMLElement.  It's a [" . gettype($X) . "].");		$elements = $X->xpath($path);		if (!is_array($elements)) throw new Exception("xpath call [{$path}] did not return an array.  It returned a [" . gettype($elements) . "].");		return $elements;	}	// Standardized short time format.	public static function shortTime($time) {		return date("g", $time) . substr(date("a", $time), 0, 1);	}	// Given a zip code, return an array of formatted weather data.	public static function getWeather($zip) {		$X = self::restCall($zip);		$fp = fopen("~/logs/xml_weather", "a");		fwrite($fp, date("c") . "\n\n");		fwrite($fp, $X->asXML() . "\n\n");		fclose($fp);		// Get the 'temperature' element		$temps = self::getPath($X, "data/parameters/temperature[@type='hourly']"); 		if (count($temps) == 0) throw new Exception("Did not find an hourly 'temperature' element.");		// There will only be one, so fetch it out of the array.		$X_Temp = current($temps);		// Now get the temperature values.		$temp_values = self::getPath($X_Temp, 'value');		if (count($temp_values) == 0) throw new Exception("Did not find any hourly temperature values.");		// Get the 'wind-speed' element.		$winds = self::getPath($X, "data/parameters/wind-speed");		if (count($winds) == 0) throw new Exception("Did not find a 'wind-speed' element.");		$X_Wind = current($winds);		$wind_values = self::getPath($X_Wind, 'value');		if (count($wind_values) == 0) throw new Exception("Did not find any wind speed values.");		// Get the 'cloud-amount' element.		$clouds = self::getPath($X, "data/parameters/cloud-amount");		if (count($clouds) == 0) throw new Exception("Did not find a 'cloud-amount' element.");		$X_Cloud = current($clouds);		$cloud_values = self::getPath($X_Cloud, 'value');		if (!is_array($temp_values)) throw new Exception("Did not find any cloud cover values.");		$temps = array();		$winds = array();		$clouds = array();		$hours = array();		$start = null;		$max_wind = 0;		// What I want is to go through the array of dates, and for each one, get the next max/min temp.  They correspond.		$Times = self::getLayout($X, $X_Temp);		foreach ($Times->{"start-valid-time"} as $Time) {			if ($start === null) $start = date("H:i:s", strtotime((string)$Time));			$hours[] = self::shortTime(strtotime((string)$Time));			$temps[] = current($temp_values);			$max_wind = max($max_wind, current($wind_values));			$winds[] = current($wind_values);			$clouds[] = current($cloud_values);			next($temp_values);			next($wind_values);			next($cloud_values);			if (count($temps) == 4) break;		}		$out = array();		$out["hours"]  = "{$zip}: " . implode(" ", $hours) . "\n";		$out["temps"]  = "F* " . implode(",", $temps) . "\n";		$out["clouds"] = "Cl: " . implode(",", $clouds) . "\n";		$out["winds"]  = "Wn: " . implode(",", $winds) . "\n";		if ($max_wind >= 20) $out["windsev"] = "Very windy\n";		else if ($max_wind >= 10) $out["windsev"] = "Windy\n";		else $out["windsev"] = "";		return $out;	}	// Format getWeather parts in the way Alpha likes.	public static function formatAlpha($parts) {		$msg = $parts["hours"];		$msg .= $parts["temps"];		$msg .= $parts["clouds"];		$msg .= $parts["winds"];		if (array_key_exists('weathers', $parts)) $msg .= $parts["weathers"];		return $msg;	}	// Format getWeather parts in the way Bravo likes.	public static function formatBravo($parts) {		$msg = $parts["hours"];		$msg .= $parts["temps"];		$msg .= $parts["clouds"];		$msg .= $parts["windsev"];		if (array_key_exists('weathers', $parts)) $msg .= $parts["weathers"];		return $msg;	}	// Send a text message to Alpha.	public static function textAlpha($msg) {		echo("Texting Alpha...\n");		$gateway_address = "foo@bar.net";		self::sendSMS($gateway_address, $msg);	}	// Send a text message to Bravo.	public static function textBravo($msg) {		echo("Texting Bravo...\n");		$gateway_address = "foo@bar.net";		self::sendSMS($gateway_address, $msg);	}	public static function sendSMS($addr, $msg) {		$msg = date("c") . "\n" . substr($msg, 0, 140 - 37);		mail($addr, "", $msg, "From: a@b.c");	}}// ***************** //// ***** LOGIC ***** //// ***************** //date_default_timezone_set('America/New_York');$dump = false;$text = false;if (php_sapi_name() == "cli") {	if ($argc == 2 && $argv[1] == "dump") $dump = true;	else if ($argc == 2 && array_search('text', $argv)) $text = true;} else if (php_sapi_name() == "cgi") {	if (array_key_exists('dump', $_GET) && $_GET['dump'] == '1') $dump = true;	else if (array_key_exists('text', $_GET) && $_GET['text'] == '1') $text = true;} else {	echo("Only CLI and CGI are allowed.  Exiting.\n");	exit;}if ($dump) {	try {		$X = BDWeather::restCall(10101);	} catch (Exception $E) {		$X = new SimpleXMLElement("<error>There was an error: [" . $E->getMessage() . "], [" . htmlspecialchars($E->result) . "]</error>");	}	header("Content-Type: text/xml");	echo($X->asXML());	exit;} else {	$sent = false;	echo("<pre>\n");	$count = 0;	$max = 20;	$sec = 15;	while ($count < $max) {		$count++;		echo(date("c") . "\n\n");		try {			$msgs = array();			if (date("N") >= 6) {				$parts = BDWeather::getWeather(10101);				$msg = BDWeather::formatAlpha($parts);				$msgs["alpha"] = $msg;				echo($msg);				var_dump(strlen($msg));				echo("\n");				$msg = BDWeather::formatBravo($parts);				$msgs["bravo"] = $msg;				echo($msg);				var_dump(strlen($msg));				echo("\n");			} else {				$parts = BDWeather::getWeather(10102);				$msg = BDWeather::formatAlpha($parts);				$msgs["alpha"] = $msg;				echo($msg . "\n\n");				var_dump(strlen($msg));				echo("\n");				$parts = BDWeather::getWeather(10101);				$msg = BDWeather::formatBravo($parts);				$msgs["bravo"] = $msg;				echo($msg . "\n\n");				var_dump(strlen($msg));				echo("\n");			}			if ($text) {				foreach ($msgs as $target => $msg) {					if ($target == 'alpha') BDWeather::textAlpha($msg);					if ($target == 'bravo') BDWeather::textBravo($msg);				}			}			$count = $max;			$sent = true;		} catch (Exception $E) {			echo("Something went wrong: [" . $E->getMessage() . "].\nSleeping for {$sec} seconds and trying again (this was attempt {$count} of {$max}).\n");			echo($E->getTraceAsString());			flush();			sleep($sec);		}	}	if (!$sent) {		echo("Could not get weather report.<br>");		if ($text) {			echo("Sending failure text messages.<br>");			BDWeather::textAlpha("Could not get weather report.  Check the log.");			BDWeather::textBravo("Sorry, I couldn't generate the weather report today.  Tell Alpha!");		}	}}