<?php // plaintext-parser.php script by Ken True - webmaster@saratoga-weather.org // // Version 0.90 - 24-Mar-2007 - Pre-release - testing and commments version // Version 0.91 - 25-Mar-2007 - fixed day/night icon glitch for translated languages // Version 0.92 - 27-Mar-2007 - added conditionals for selective printing, optional degrees, and // capitalization for First letter of sentence in translation. // Version 1.00 - 30-Mar-2007 - changed primary parsing to support IIS, and added minPoP to // display sky condition (with pop) instead of rain icon. // Version 1.01 - 02-Apr-2007 - support for UTF-8 display, translation of City names, Date format option // Version 1.02 - 16-May-2007 - minor change to allow operation with plaintext-rss.php // Version 1.03 - 03-Jun-2007 - Added Wind dir/speed/units forecast and changed table generation method // Version 1.04 - 27-Jul-2007 - Added Beaufort options for wind speed display // Version 1.05 - 04-Aug-2007 - Modified Beaufort to use 'mps' or 'm/s' for meters-per-second // $Version = "plaintext-parser.php Version 1.05 - 04-Aug-2007"; // // error_reporting(E_ALL); // uncomment to turn on full error reporting // // script available at http://saratoga-weather.org/scripts.php // // you may copy/modify/use this script as you see fit, // no warranty is expressed or implied. // // This script parses the plaintext.txt forecast output from WXSIM // (http://www.wxsim.com/) to create a HTML page that resembles // the NOAA NWS point-printable forecast page in the carterlake advforecast.php style. // // output: creates XHTML 1.0-Strict HTML page (or inclusion) // // This script requires the NOAA icons and the icons need to be placed in the path // where the original NOAA icons are located: \forecast\images\ // (so make a folder in your web HTML root called "forecast", then make a folder in it // called "images", and place the icons in this folder) // The icon set is available at http://saratoga-weather.org/carterlake-icons.zip // If you have the icon set from: // http://members.cox.net/carterlakeweather/forecasticons.zip (380K) // then please download http://saratoga-weather.org/carterlake-icons-addon.zip and // upload to your /forecast/images directory. It contains images to support the // "show sky conditions when chance rain and PoP < $minPoP" logic. // // // Options on URL: // lang=en (default) - use English language // lang=ZZ - use 'ZZ' language translation file for conversion from English // note: there must be a plaintext-parser-lang-LL.txt file with the // conversion rules. A sample Dutch file is included (lang=nl). // // inc=Y - omit <HTML><HEAD></HEAD><BODY> and </BODY></HTML> from output // heading=n - (default)='y' suppress printing of heading (forecast city/by/date) // icons=n - (default)='y' suppress printing of the icons+conditions+temp+wind+UV // text=n - (default)='y' suppress printing of the periods/forecast text // // // You can also invoke these options directly in the PHP like this // // $doInclude = true; // include("plaintext-parser.php"); for just the text // or ------------ // $doPrint = false; // include("plaintext-parser.php"); for setting up the $WXSIM... variables without printing // // or ------------ // $doInclude = true; // $doPrintHeading = true; // $doPrintIcons = true; // $doPrintText = false // include("plaintext-parser.php"); include mode, print only heading and icon set // // Variables returned (useful for printing an icon or forecast or two...) // // $WXSIMcity - Name of city from WXSIM Forecast header // $WXSIMstation - (in settings below) Name of forecaster or weather station // $WXSIMupdated - Time of forecast from WXSIM Forecast header // // The following variables exist for $i=0 to $i= number of forecast periods minus 1 // a loop of for ($i=0;$i<count($WXSIMday);$i++) { ... } will loop over the available // values. // // $WXSIMday[$i] - period of forecast (translated) // $WXSIMtext[$i] - text of forecast (translated) // $WXSIMuv[$i] - UV index value (number) // note: you can use 'set_UV_string($WXSIMuv[$i])' to get a UV N and meaning text // $WXSIMtemp[$i] - Temperature with translated text and formatting // $WXSIMpop[$i] - Number - Probabability of Precipitation ('',10,20, ... ,100) // $WXSIMprecip[$i] - amount of precipitation (native units from plaintext forecast) // $WXSIMicon[$i] - base name of icon graphic to use // $WXSIMcond[$i] - Short legend for forecast icon (translated) // $WXSIMicons[$i] - Full icon with translated Period, <img> and Short legend. // the following were added in V1.03: // $WXSIMwinddir[$i]- Wind direction ( may be something like 'SSE' or 'NW->N' ) (translated) // $WXSIMwind[$i] - Wind speed (may be something like '10' or '7->4' or '10-16->6' ) // $WXSIMgust[$i] - Wind gust // $WXSIMwindunits[$i] - Wind speed units (mph, kph, mps, kts) (translated) // $WXSIMBeaufort[$i] - Beaufort scale for max wind speed 'n Bft' or 'Light air' (translated) // Note: // // Settings --------------------------------------------------------------- $iconDir ='./forecast/images/'; // directory for carterlake icons $WXSIMstation = "Saratoga-Weather.org"; // name of your weather station $plaintextFile = './plaintext.txt'; // location of the WXSIM plaintext.txt $lang = 'en'; // default language is 'en' = English $tempDegrees = '°'; // set to '' to omit degree sign // // or set to '°', '°F' or '°C' $maxWidth = '640px'; // max width of tables (could be '100%') $minPoP = '40'; // PoP must be this or above to display // // rain icon, otherwise sky icon w/PoP displayed. $showBeaufort = 'T'; // set to false to not display Beaufort at all // // ='V' for 'n Bft', ='T' for translated name // ---- end of settings --------------------------------------------------- // // -------------------begin code ------------------------------------------ if (isset($_REQUEST['sce']) && strtolower($_REQUEST['sce']) == 'view' ) { //--self downloader -- $filenameReal = $_SERVER["PATH_TRANSLATED"]; $filenameLcl = substr($PHP_SELF,1); $download_size = filesize($filenameReal); header('Pragma: public'); header('Cache-Control: private'); header('Cache-Control: no-cache, must-revalidate'); header("Content-type: text/plain"); header("Accept-Ranges: bytes"); header("Content-Length: $download_size"); header('Connection: close'); readfile($filenameReal); exit; } $Status = "<!-- $Version -->\n"; $doTranslate = true; if (isset($_REQUEST['lang']) ) { $lang=strtolower($_REQUEST['lang']); if ($lang == 'en') { $doTranslate = false; }; } $doDebug = false; if (isset($_REQUEST['debug']) ) { $doDebug = substr(strtolower($_REQUEST['debug']),0,1) == 'y'; } $printHeading = true; $printIcons = true; $printText = true; if (isset($doPrintHeading)) { $printHeading = $doPrintHeading; } if (isset($_REQUEST['heading']) ) { $printHeading = substr(strtolower($_REQUEST['heading']),0,1) == 'y'; } if (isset($doPrintIcons)) { $printIcons = $doPrintIcons; } if (isset($_REQUEST['icons']) ) { $printIcons = substr(strtolower($_REQUEST['icons']),0,1) == 'y'; } if (isset($doPrintText)) { $printText = $doPrintText; } if (isset($_REQUEST['text']) ) { $printText = substr(strtolower($_REQUEST['text']),0,1) == 'y'; } $useCharSet = 'iso-8859-1'; $UTFLang = ',gr,ru,cn,jp,'; // languages needing UTF-8 character set for display $timeFormat = 'd-M-Y h:i a'; // default to USA format // load the config file $config = file("./plaintext-parser-data.txt"); // // load and merge the language file (if it exists) if ($doTranslate and $lang <> 'en' and file_exists("./plaintext-parser-lang-$lang.txt") ) { $lfile = file("./plaintext-parser-lang-$lang.txt"); foreach ($lfile as $val) { array_push($config,$val); } $Status .= "<!-- translation file for '$lang' loaded -->\n"; if (strpos($UTFLang,$lang) > 0) {$useCharSet = 'UTF-8'; $Status .= "<!-- using UTF-8 -->\n";} } else { $doTranslate = false; if($lang <> 'en') { $Status .= "<!-- translation file for '$lang' not found -->\n"; $lang = 'en'; } } // Initialize -- read in control file and place in $Conditions and $Precip // for later use $LanguageLookup = array(); $WindLookup = array( // initialized by wind-direction abbreviations for icons // NOTE: don't change these .. use LANGLOOKUP entries in the plaintext-parser-LL.txt // translation control file instead. 'north' => 'N', 'north-northeast' => 'NNE', 'northeast' => 'NE', 'east-northeast' => 'ENE', 'east' => 'E', 'east-southeast' => 'ESE', 'southeast' => 'SE', 'south-southeast' => 'SSE', 'south' => 'S', 'south-southwest' => 'SSW', 'southwest' => 'SW', 'west-southwest' => 'WSW', 'west' => 'W', 'west-northwest' => 'WNW', 'northwest' => 'NW', 'north-northwest' => 'NNW' ); $BeaufortText = array( // NOTE: don't change these .. use LANGLOOKUP entries in the plaintext-parser-LL.txt // translation file instead. 'Calm', 'Light air', 'Light breeze','Gentle breeze', 'Moderate breeze', 'Fresh breeze', 'Strong breeze', 'Near gale', 'Gale', 'Strong gale', 'Storm', 'Violent storm', 'Hurricane' ); // wind speed < values below correspond to force 0 .. 11 . >= last value = force 12 $BeaufortKTS = array( 1,4,7,11,17,22,28,34,41,48,56,64,64 ); $BeaufortMPH = array( 1,4,8,13,19,25,32,39,47,55,64,73,73 ); $BeaufortKPH = array( 1,6,12,20,30,40,51,63,76,88,103,118,118 ); $BeaufortMS = array( 0.2,1.6,3.4,5.5,8.0,10.8,13.9,17.2,20.8,24.5,28.5,32.7,32.7 ); reset($config); // $Status .= "<!-- config: \n" . print_r($config,true) . " -->\n"; foreach ($config as $key => $rec) { // load the parser condition strings $recin = trim($rec); if ($recin and substr($recin,0,1) <> '#') { // got a non comment record list($type,$keyword,$dayicon,$nighticon,$condition) = explode('|',$recin . '|||||'); if (isset($type) and strtolower($type) == 'cond' and isset($condition)) { $Conditions["$keyword"] = "$dayicon\t$nighticon\t$condition"; } if (isset($type) and strtolower($type) == 'precip' and isset($nighticon)) { $Precip["$keyword"] = "$dayicon\t$nighticon"; } if (isset($type) and strtolower($type) == 'lang' and isset($dayicon)) { $Language["$keyword"] = "$dayicon"; } if (isset($type) and strtolower($type) == 'langlookup' and isset($dayicon)) { $LanguageLookup["$keyword"] = "$dayicon"; } if (isset($type) and strtolower($type) == 'dateformat' and isset($keyword)) { $timeFormat = trim($keyword); } } // end if not comment or blank } // end loading of $Conditions and $Precip if (count($LanguageLookup) < 1) {$doTranslate = false; } $testFiles = array( // local testing for Ken .. these files aren't part of the distribution 'a' => 'plaintext-bin.txt', 'b' => 'plaintext-test1.txt', 'fr' => 'plaintext-cy.txt', 'nl' => 'plaintext-du.txt', 'it' => 'plaintext-it.txt', 'se' => 'plaintext-se.txt', 'snow' => 'plaintext-snow.txt', 'rest' => 'plaintext-rest.txt', 'oregon' => 'plaintext-oregon.txt', 'fograin' => 'plaintext-fograin.txt', 'snow2' => 'plaintext-snow2.txt', 'gr' => 'plaintext-gr.txt' ); if (isset($_REQUEST['test']) ) { // for testing only $t = strtolower($_REQUEST['test']); if (isset($testFiles[$t]) ) { $Status .= "<!-- using $testFiles[$t] for plaintext.txt -->\n"; $plaintextFile = $testFiles[$t]; } } if (isset($_REQUEST['minpop'])) { // for testing only $minPoP = $_REQUEST['minpop']; } // Read in the plaintext.txt forecast file for processing $pt = file($plaintextFile); $plaintext = implode('',$pt); // get the plaintext file. // preprocess.. mark divisions in the forecast days for later parsing $plaintext = preg_replace('![\r|\n]+ [\r|\n]+!s',"\t\t",$plaintext); $plaintext .= "\t\t"; // make sure a delimiter is at the end too. $plaintext = preg_replace('|_|is','',$plaintext); // remove dashed line in front // Find city and update date if (preg_match('|WXSIM text forecast for (.*), initialized at\s+(.*)|i',$plaintext,$matches)) { $WXSIMcity = get_lang(trim($matches[1])); $wdate = trim($matches[2]); $Status .= "<!-- wdate '$wdate' -->\n"; // there are LOTS of formats of the date stamp in plaintext.txt // 012345678901234567890 // 20:00 Feb 21, 2007 // 15:00 02 Apr, 2007 // 20:00 Feb 21, 2007 // 21:00 25 Mar, 2007 // 8:00 PM Mar 24, 2007 // 12:00 AM 24 Mar, 2007 $wdateParts = preg_split("/[\s,]+/", $wdate); // $Status .= "<!-- wdate split\n" . print_r($wdateParts,true) . " -->\n"; $i=0; if (preg_match('!AM|PM!i',$wdateParts[1]) ) { // got US style date. list($wHrs,$wMins) = split(':',$wdateParts[0]); if (strtolower($wdateParts[1]) == 'pm' and $wHrs <> 12 ) {$wHrs += 12; } if (strtolower($wdateParts[1]) == 'am' and $wHrs == 12 ) {$wHrs = '00'; } $wTime = "$wHrs:$wMins"; $i=1; } else { $wTime = $wdateParts[0]; } if (preg_match('!\d+!',$wdateParts[$i+1]) ) { // got day in 1, month in 2 (+offset) $wDay = $wdateParts[$i+1]; $wMon = $wdateParts[$i+2]; } else { $wDay = $wdateParts[$i+2]; $wMon = $wdateParts[$i+1]; } $wYear = $wdateParts[$i+3]; // $wdate = preg_replace('|(\S+)\s+(\S+)\s+(\S+),\s+(\S+)|s',"$2-$3-$4 $1:00 ".date('O',time()),$wdate); $wdate = "$wDay-$wMon-$wYear $wTime " . date('O',time()); $Status .= "<!-- updated '$wdate'-->\n"; $d = strtotime($wdate); $WXSIMupdated = get_lang(date('l',$d)) . ', ' . date($timeFormat,$d); } // split up the forecast days and texts // good preg_match_all('![\r|\n]+\s+(.*):\s(.*)[\r|\n]+ [\r|\n]+!Us',$plaintext,$matches); preg_match_all('!\t\s(.*):\s(.*)\t!Us',$plaintext,$matches); // split up the forecast // Main loop over each forecast text paragraph. for ($i=0;$i<count($matches[1]);$i++) { // loop over results by forecast period and peel out values $WXSIMday[$i] = trim($matches[1][$i]); $WXSIMtext[$i] = preg_replace('![\r|\n]+!is','',trim($matches[2][$i])); // remove CR and LF chars. // initialize this day's variables $WXSIMuv[$i] = ''; $WXSIMtemp[$i] = ''; $WXSIMpop[$i] = ''; $WXSIMprecip[$i] = ''; $WXSIMicon[$i] = ''; $WXSIMcond[$i] = ''; $WXSIMtempdirect[$i] = ''; $WXSIMwinddir[$i] = ''; $WXSIMwinddiricon[$i] = ''; $WXSIMwind[$i] = ''; $WXSIMgust[$i] = ''; $WXSIMwindunits[$i] = ''; // make the period 'pretty' with HTML breaks. $WXSIMtitles[$i] = preg_replace('! (\S+)$!',"<br />\\1",get_lang($WXSIMday[$i])); if (! preg_match('!<br />!',$WXSIMtitles[$i])) { $WXSIMtitles[$i] .= '<br />'; // add line break to 'short' day titles } // extract UV index value if (preg_match('|UV index up to (\d+)\.|i',$WXSIMtext[$i],$mtemp) ) { $WXSIMuv[$i] = $mtemp[1]; } // extract Wind direction, values $testwind = str_replace('Wind chill','Wind-chill',$WXSIMtext[$i]); if (preg_match('|Wind (.*)\.|Ui',$testwind,$mtemp) ) { // $Status .= "<!-- mtemp[1]='" . $mtemp[1] . "' -->\n"; $wtemp = preg_replace( '! around| near| in the| morning| evening| afternoon| midnight| tonight| to| after!Uis', '',$mtemp[1]); // $Status .= "<!-- stripped='" . $wtemp . "' -->\n"; $wtemp = explode(', ',$wtemp); // $Status .= "<!-- wind\n" . print_r($wtemp, true) . " -->\n"; // [0] => northwest around 5 mph // or // [0] => northwest near calm // [1] => gusting to 12 mph // [2] => in the morning // [3] => becoming 12 mph in the afternoon // or // [3] => becoming west-northwest around 12 mph in the afternoon // or // [3] => becoming north-northwest in the afternoon $wparts = explode(' ',$wtemp[0]); // break it by spaces. $maxWind = 0; for ($k =0;$k<count($wtemp);$k++) { $wparts = explode(' ',$wtemp[$k]); if(isset($WindLookup[$wparts[0]]) ) { // got <dir> [speed] [units] format $WXSIMwinddir[$i] = $WindLookup[$wparts[0]]; // get abbreviation for direction $WXSIMwinddiricon[$i] = $WXSIMwinddir[$i]; // base name for wind icon $WXSIMwind[$i] = $wparts[1]; // get speed if ($wparts[1] > $maxWind and $wparts[1] <> 'calm') { $maxWind = $wparts[1]; } if ( isset($wparts[2])) { $WXSIMwindunits[$i] = $wparts[2]; // get wind units of measure } } if ($wparts[0] == 'gusting') { $WXSIMwind[$i] .= '-' . $wparts[1]; if ($wparts[1] > $maxWind) { $maxWind = $wparts[1]; } $WXSIMgust[$i] = $wparts[1]; } if ($wparts[0] == 'becoming') { // got 'becoming [dir] [speed] [units] if (isset($WindLookup[$wparts[1]]) ) { $WXSIMwinddir[$i] .= '⇒' . $WindLookup[$wparts[1]]; } if (preg_match('!(\d+|calm)!',$wtemp[$k],$match)) { $WXSIMwind[$i] .= '⇒' . $match[1]; if ($match[1] > $maxWind and $match[1] <> 'calm') { $maxWind = $match[1]; } } if (! $WXSIMwindunits[$i] and isset($wparts[2]) ) { $WXSIMwindunits[$i] = $wparts[2]; // get wind units of measure } } } $WXSIMBeaufort[$i] = displayBeaufort(getBeaufort($maxWind,$WXSIMwindunits[$i])) ; $Status .= "<!-- dir='" . $WXSIMwinddir[$i] . "' wind='" . $WXSIMwind[$i] . "' gust='" . $WXSIMgust[$i] . "' units='" . $WXSIMwindunits[$i] . "' maxWind = '$maxWind' Beaufort='" . $WXSIMBeaufort[$i] . "'-->\n"; } // extract temperature High/Low values if (preg_match('!(high|low) ([-|\d]+)[\.|,]!i',$WXSIMtext[$i],$mtemp)) { $WXSIMtemp[$i] = get_lang($mtemp[1] .':') . ' ' . $mtemp[2] . $tempDegrees; if ($tempDegrees) { // fix up degrees in the text $WXSIMtext[$i] = preg_replace( '|' . $mtemp[1] . ' ' . $mtemp[2] .'|', $mtemp[1] . ' ' . $mtemp[2] . $tempDegrees, $WXSIMtext[$i]); } if(substr($mtemp[1],0,1) == 'H') { $WXSIMtemp[$i] = '<span style="color: red">' . $WXSIMtemp[$i] . '</span>'; } else { $WXSIMtemp[$i] = '<span style="color: blue">' . $WXSIMtemp[$i] . '</span>'; } } if (preg_match('!temperatures (rising|falling)!i',$WXSIMtext[$i],$mtemp)) { $WXSIMtempdirect[$i] = $mtemp[1]; } // extract PoP if (preg_match('!Chance of precipitation (.*) percent!i',$WXSIMtext[$i],$mtemp)) { // print "<pre>" . print_r($mtemp,true) . "</pre>\n"; $WXSIMpop[$i] = $mtemp[1]; $WXSIMpop[$i] = preg_replace('|less than |i','<',$WXSIMpop[$i]); if ($WXSIMpop[$i] == '<20') {$WXSIMpop[$i] = '10';} if ($WXSIMpop[$i] == 'near 100') { $WXSIMpop[$i] = '100'; } } // now look for harshest conditions first.. (in order in -data file reset($Conditions); // Do search in load order foreach ($Conditions as $cond => $condrec) { // look for matching condition if(preg_match("!$cond!i",$WXSIMtext[$i],$mtemp)) { list($dayicon,$nighticon,$condition) = explode("\t",$condrec); if (preg_match('!chance!i',$condition) and $WXSIMpop[$i] < $minPoP) { continue; // skip this one } $WXSIMcond[$i] = get_lang($condition); if (preg_match('|night|i',$WXSIMday[$i])) { $WXSIMicon[$i] = $nighticon; } else { $WXSIMicon[$i] = $dayicon; } break; } } // end of conditions search // look for precipitation amounts reset($Precip); // Do search in load order foreach ($Precip as $pamt => $prec) { // look for matching precipitation amounts if(preg_match("!$pamt!is",$WXSIMtext[$i],$mtemp)) { list($amount,$units) = explode("\t",$prec); $WXSIMprecip[$i] = $amount . ' ' . $units; break; } } // end of precipitation amount search // now fix up the full icon name and PoP if available $curicon = $WXSIMicon[$i] . '.jpg'; if ($WXSIMpop[$i] > 0) { $testicon = preg_replace("|\.jpg|","$WXSIMpop[$i].jpg",$curicon); // print "<pre>testicon='$testicon'</pre>\n"; if (file_exists($iconDir . $testicon)) { $WXSIMicon[$i] = $testicon; } else { $WXSIMicon[$i] = $curicon; } } else { $WXSIMicon[$i] = $curicon; } if ($WXSIMtempdirect[$i] <> '') { $tempdirect = 'up.gif'; if (substr($WXSIMtempdirect[$i],0,1) == 'f') { $tempdirect='down.gif'; } $WXSIMtemp[$i] .= "<img src=\"$iconDir$tempdirect\" height=\"10\" width=\"10\" alt=\" \" />"; } if ($doTranslate) { // perform optional translation if $Language has entries reset ($Language); // process in order of the file $text = $WXSIMtext[$i]; foreach ($Language as $key => $replacement) { $text = str_replace($key,$replacement,$text); } // put back translated text, fixing capitalization for sentence starts (except the first one). $WXSIMtext[$i] = preg_replace('!\.\s+([a-z])!es',"'. ' . strtoupper('\\1')",$text); $WXSIMday[$i] = get_lang($WXSIMday[$i]); $wdirs = get_lang('NESW'); // default directions $WXSIMwinddir[$i] = strtr($WXSIMwinddir[$i],'NESW',$wdirs); // do translation // translate speed and wind units based on lang entries in one pass $text = ' ' . $WXSIMwind[$i] . " \t " . $WXSIMwindunits[$i] . ' '; // make test string. reset ($Language); // process in order of the file foreach ($Language as $key => $replacement) { $text = str_replace($key,$replacement,$text); } $key = explode("\t",$text); $WXSIMwind[$i] = trim($key[0]); $WXSIMwindunits[$i] = trim($key[1]); } // make HTML for full icon with condition description $WXSIMicons[$i] = "$WXSIMtitles[$i]<br /> <img src=\"$iconDir$WXSIMicon[$i]\" alt=\"$WXSIMcond[$i]\" title=\"$WXSIMcond[$i]\" /><br /> $WXSIMcond[$i]"; } // end of main loop ------------------------- $IncludeMode = false; $PrintMode = true; if (isset($doPrint) && ! $doPrint ) { // print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'noprint' ) { // print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'y') { $IncludeMode = true; } if (isset($doInclude)) { $IncludeMode = $doInclude; } // V1.03 -- set width of <td> for icons based on overall width/num icons preg_match('|(\d+)(.*)|',$maxWidth,$widthparts); //$Status .= "<!-- widthparts\n" . print_r($widthparts,true) . " -->\n"; $nTD = count($WXSIMicon); if ($nTD < 1) { $nTD = 1; } $wTD = round($widthparts[1]/$nTD,0) . $widthparts[2]; $Status .= "<!-- maxWidth='$maxWidth' nTD=$nTD wTD='$wTD' -->\n"; //begin printing of advforecast style printout if(! $IncludeMode) { ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $useCharSet; ?>" /> <title><?php echo $Version; ?></title> </head> <body style="background-color:#FFFFFF; font-family:Arial, Helvetica, sans-serif; font-size: 10pt"> <?php } // only print above if not include mode print $Status; if ($printHeading or $printIcons) { ?> <div class="WXSIMforecast"> <table width="<?php echo $maxWidth; ?>" style="border: none;"> <?php } if ($printHeading) { ?> <tr align="center"> <td><b><?php echo get_lang("WXSIM Forecast for:");?> </b><span style="color: green;"> <?php echo $WXSIMcity; ?></span><br /> <?php echo get_lang("Issued by:"); ?> <?php echo $WXSIMstation; ?> </td> </tr> <tr> <td align="center"><?php echo get_lang("Updated:");?> <?php echo $WXSIMupdated; ?> </td> </tr> <?php } // end printHeading if ($printIcons) { ?> <tr> <td align="center"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr valign ="top" align="center"> <?php for ($i=0;$i<count($WXSIMicons);$i++) { print "<td style=\"width: $wTD;\"><span style=\"font-size: 8pt;\">$WXSIMicons[$i]</span></td>\n"; } ?> </tr> <tr valign ="top" align="center"> <?php for ($i=0;$i<count($WXSIMprecip);$i++) { print "<td style=\"width: $wTD; color: green;\">$WXSIMprecip[$i]</td>\n"; } ?> </tr> <tr valign ="top" align="center"> <?php for ($i=0;$i<count($WXSIMtemp);$i++) { print "<td style=\"width: $wTD;\">$WXSIMtemp[$i]</td>\n"; } ?> </tr> <tr valign ="top" align="center"> <?php for ($i=0;$i<count($WXSIMwinddir);$i++) { print "<td style=\"width: $wTD;\">" . $WXSIMwinddir[$i] . "<br/> " . $WXSIMwind[$i] . "<br/> " . $WXSIMwindunits[$i]; if ($showBeaufort) { print "<br/><i>" . $WXSIMBeaufort[$i] ."</i>"; } print "</td>\n"; } ?> </tr> <tr valign ="top" align="center"> <?php for ($i=0;$i<count($WXSIMuv);$i++) { print "<td style=\"width: $wTD;\">" . set_UV_string($WXSIMuv[$i]) . "</td>\n"; } ?> </tr> </table> </td> </tr> <?php } // end printIcons if ($printHeading or $printIcons) { ?> </table> </div> <p> </p> <?php } // end heading and icons if ($printText) { ?> <div class="WXSIMforecast"> <table style="border: 0" width="<?php echo $maxWidth; ?>"> <?php for ($i=0;$i<count($WXSIMday);$i++) { print "<tr valign =\"top\" align=\"left\">\n"; print "<td style=\"width: 20%;\"><b>$WXSIMday[$i]</b><br /> <br /></td>\n"; print "<td style=\"width: 80%;\">$WXSIMtext[$i]</td>\n"; print "</tr>\n"; } ?> </table> <p><small><a href="http://www.wxsim.com/">WXSIM</a> forecast formatting script by <a href="http://saratoga-weather.org/scripts.php">Saratoga-Weather.org</a>.</small></p> </div><?php } // end printText if (! $IncludeMode) { ?> </body> </html> <?php } // print above only if not include mode // Functions ----------------------------------------------------------------------- // replace text with language lookup text if available function get_lang( $text ) { global $LanguageLookup, $doTranslate; if ($doTranslate && isset($LanguageLookup[$text])) { $newtext = $LanguageLookup[$text]; } else { $newtext = $text; } return($newtext); } // decode UV to word+color for display function set_UV_string ( $uv ) { // figure out a text value and color for UV exposure text // 0 to 2 Low // 3 to 5 Moderate // 6 to 7 High // 8 to 10 Very High // 11+ Extreme switch (TRUE) { case ($uv == 0): $uv = ''; break; case (($uv > 0) and ($uv < 3)): $uv = "UV: $uv<br/>" . '<span style="border: solid 1px; background-color: #A4CE6a;"> ' . get_lang("Low") .' </span>'; break; case (($uv >= 3) and ($uv < 6)): $uv = "UV: $uv<br/>" . '<span style="border: solid 1px;background-color: #FBEE09;"> ' . get_lang("Medium") .' </span>'; break; case (($uv >=6 ) and ($uv < 8)): $uv = "UV: $uv<br/>" . '<span style="border: solid 1px; background-color: #FD9125;"> ' . get_lang("High") .' </span>'; break; case (($uv >=8 ) and ($uv < 11)): $uv = "UV: $uv<br/>" . '<span style="border: solid 1px; color: #FFFFFF; background-color: #F63F37;"> ' . get_lang('Very High') . ' </span>'; break; case (($uv >= 11) ): $uv = "UV: $uv<br/>" . '<span style="border: solid 1px; color: #FFFF00; background-color: #807780;"> ' . get_lang("Extreme") .' </span>'; break; } // end switch return $uv; } // end get_UVrange // determine Beaufort number based on wind speed and units function getBeaufort ( $wind, $units) { global $showBeaufort,$BeaufortMPH,$BeaufortKPH,$BeaufortKTS,$BeaufortMS; switch ($units) { case 'mph': $winds = $BeaufortMPH; break; case 'kph': $winds = $BeaufortKPH; break; case 'm/s': $winds = $BeaufortMS; break; case 'mps': $winds = $BeaufortMS; break; case 'kts': $winds = $BeaufortKTS; break; } // end switch $Bft = 0; for ($i=0;$i<12;$i++) { if ($wind < $winds[$i]) { $Bft = $i; break; } } if ($i == 11 and ! $Bft) { $Bft = 12; }; return($Bft); }// end getBeaufort // perform Beaufort display if desired by showBeaufort setting function displayBeaufort ($Bft) { global $showBeaufort, $BeaufortText; if ($Bft < 0 or $Bft > 12 ) { return(""); } if ($showBeaufort == 'T') { return( get_lang($BeaufortText[$Bft]) ); } if ($showBeaufort == 'V') { return("$Bft Bft"); } return(""); }// end displayBeaufort ?>