home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2005 June / PCpro_2005_06.ISO / files / opensource / xamp / xampp-win32.exe / xampp / metar-extensive.php < prev    next >
Encoding:
PHP Script  |  2004-10-01  |  27.0 KB  |  598 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Alexander Wirtz <alex@pc4p.net>                             |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: metar-extensive.php,v 1.10 2004/07/11 21:44:37 eru Exp $
  20.  
  21. /*
  22.  * Well, this is a more elaborate example how to create a neat little page
  23.  * with fetching METAR/TAF data from noaa.org and putting it into a design.
  24.  * I'm not too proud of my design-skills, most of the stuff here is taken
  25.  * from the metar-block which can be found within the Horde Framework,
  26.  * courtesy of Rick Emery - creative pixelshoving isn't my domain :-P
  27.  * I've used a Firefox for checking the design, so don't be too
  28.  * disappointed, if the page looks shabby with the IE, not that I care
  29.  * very much anyway ;-)
  30.  * Have fun!
  31. */
  32.  
  33. //-------------------------------------------------------------------------
  34. // This is the area, where you can customize the script
  35. //-------------------------------------------------------------------------
  36. $location        = "Bonn, Germany"; // The city we want to fetch the data for.
  37.                                     // Where the search function will look for
  38.                                     // the ICAO database (generated with the
  39.                                     // buildMetarDB.php script)
  40. $dsn             = "sqlite://localhost//usr/local/lib/php/data/Services_Weather/servicesWeatherDB"; 
  41. $sourceMetar     = "http";          // This script will pull the METAR data via http
  42. $sourceTaf       = "http";          //                           TAF
  43. $sourcePathMetar = "";              // Only needed when non-standard access is used
  44. $sourcePathTaf   = "";              //
  45. $cacheType       = "";              // Set a type (file, db, mdb, ...) to
  46.                                     // enable caching.
  47. $cacheOpt        = array();         // Cache needs various options, depending
  48.                                     // on the container-type - please consult
  49.                                     // the Cache manual / sourcecode!
  50. $unitsFormat     = "metric";        // The format the units are displayed in -
  51.                                     // metric, standard or some customization.
  52. $dateFormat      = "j. M Y";        // Set the format the date is displayed in
  53. $timeFormat      = "H:i";           //                    time
  54. //-------------------------------------------------------------------------
  55.  
  56. // Load the Weather class
  57. require_once "Services/Weather.php";
  58. // Load the scripts needed for sunrise/-set calculation
  59. include_once "php_sunrise_sunset.php";
  60.  
  61. // Object initialization - error checking is important, because of
  62. // handling exceptions such as missing PEAR modules
  63. $metar = &Services_Weather::service("Metar");
  64. if (Services_Weather::isError($metar)) {
  65.     die("Error: ".$metar->getMessage()."\n");
  66. }
  67.  
  68. // Set parameters for DB access, needed for location searches
  69. $metar->setMetarDB($dsn);
  70. if (Services_Weather::isError($metar)) {
  71.     echo "Error: ".$metar->getMessage()."\n";
  72. }
  73.  
  74. // Initialize caching
  75. if (strlen($cacheType)) {
  76.     $status = $metar->setCache($cacheType, $cacheOpt);
  77.     if (Services_Weather::isError($status)) {
  78.         echo "Error: ".$status->getMessage()."\n";
  79.     }
  80. }
  81.  
  82. // Define the units format, bring the retrieved format into
  83. // something more common...
  84. $metar->setUnitsFormat($unitsFormat);
  85. $units = $metar->getUnitsFormat();
  86. $units["temp"]   = "°".strtoupper($units["temp"]);
  87. $units["wind"]   = " ".str_replace("kmh", "km/h", $units["wind"]);
  88. $units["vis"]    = " ".$units["vis"];
  89. $units["height"] = " ".$units["height"];
  90. $units["pres"]   = " ".$units["pres"];
  91. $units["rain"]   = " ".$units["rain"];
  92.  
  93. $metar->setMetarSource($sourceMetar, $sourcePathMetar, $sourceTaf, $sourcePathTaf);
  94.  
  95. // Set date-/time-format
  96. $metar->setDateTimeFormat($dateFormat, $timeFormat);
  97.  
  98. // Search for defined location and fetch the first item found.
  99. // Bail out if something bad happens...
  100. $search = $metar->searchLocation($location, true);
  101. if (Services_Weather::isError($search)) {
  102.     die("Error: ".$search->getMessage()."\n");
  103. }
  104.  
  105. // Retrieve data, store in variables, bail out on error
  106. $fetch = array(
  107.     "location" => "getLocation",
  108.     "weather"  => "getWeather",
  109.     "forecast" => "getForecast"
  110. );
  111. foreach ($fetch as $variable => $function) {
  112.     $$variable = $metar->$function($search);
  113.     if (Services_Weather::isError($$variable)) {
  114.         echo "Error: ".$$variable->getMessage()."\n";
  115.         continue;
  116.     }
  117. }
  118.  
  119. // Calculate sunrise/-set for our location - UTC is used here!
  120. $gmt_offset = 0;
  121. $timestamp  = gmmktime();
  122. $location["sunrise"] = date_sunrise($timestamp, "", $location["latitude"], $location["longitude"], "", $gmt_offset);
  123. $location["sunset"]  = date_sunset($timestamp, "", $location["latitude"], $location["longitude"], "", $gmt_offset);
  124.  
  125. // Now we output all the data, please don't expect extensive comments here, this is basic
  126. // HTML/CSS stuff. Also this isn't a very fancy design, it's just to show you, what
  127. // the script is able to do (and more ;-))...
  128. ?>
  129. <html>
  130. <head>
  131.     <title>Services_Weather::METAR/TAF</title>
  132.     <style type="text/css">
  133.         .normal     { font-family: Arial, Helvetica, sans-serif; font-size: 11pt; font-weight: normal; font-style: normal }
  134.         .italic     { font-weight: normal; font-style: italic }
  135.         .bold       { font-weight: bold; font-style: normal }
  136.         .bolditalic { font-weight: bold; font-style: italic }
  137.         .redbold    { font-weight: bold; font-style: normal; color: #ff0000 }
  138.         .bluebold   { font-weight: bold; font-style: normal; color: #0000ff }
  139.         .bggrey     { background-color: #e9e9e9 }
  140.         .bgkhaki    { background-color: #d8d8c0 }
  141.         .reg        { font-size: 7pt; vertical-align: super }
  142.         img         { vertical-align: middle; border-style: none; border-width: 0px }
  143.         a           { font-weight: bold; font-style: italic; color: #993300; text-decoration: none }
  144.         a:visited   { font-weight: bold; font-style: italic; color: #993300; text-decoration: none }
  145.         a:hover     { font-weight: bold; font-style: italic; color: #cc3300; text-decoration: underline }
  146.         table       { border: 0px none black; border-spacing: 0px }
  147.         td          { font-family: Arial, Helvetica, sans-serif; font-size: 11pt; font-weight: normal; font-style: normal }
  148.     </style>
  149. </head>
  150. <body class="normal">
  151. <?php
  152. // Debug outputs the raw data fetched by the foreach-loop above, just for checking...
  153. if (isset($_GET["debug"])) {
  154.     echo "<pre>\n";
  155.     var_dump($location, $weather, $forecast);
  156.     echo "</pre>\n";
  157. ?>
  158. <span class="bluebold" style="font-size: 13pt">Weather Forecast</span> created with <a style="font-size: 13pt" href="http://pear.php.net/">PEARs</a> <a style="font-size: 13pt" href="http://pear.php.net/package/Services_Weather/">Services_Weather</a><br>
  159. <table style="width: 100%">
  160. <tr>
  161.     <td>
  162.         <table border="0" style="border-top: 2px solid #524b98; border-bottom: 2px solid #e0e3ce; border-left: 2px solid #b8b6c1; border-right: 2px solid #8b87a0; width: 100%">
  163.         <tr class="bgkhaki">
  164.             <td colspan="4" style="border-bottom: 2px solid #abada2"><span class="bold"><?=$location["name"]?> (<?=$search?>)</span></td>
  165.         </tr>
  166.         <tr>
  167.             <td><span class="bold">Sunrise:</span> <img style="width: 28px; height: 13px; vertical-align: baseline" alt="Sunrise" src="images/sunrise.gif"> <?=$location["sunrise"]?></td>
  168.             <td><span class="bold">Sunset:</span> <img style="width: 30px; height: 15px; vertical-align: baseline" alt="Sunset" src="images/sunset.gif"> <?=$location["sunset"]?></td>
  169.             <td style="width: 190px"> </td>
  170.             <td style="width: auto"> </td>
  171.         </tr>
  172.         <tr style="height: 15px">
  173.             <td nowrap><span class="bold">Temperature:</span> <?=round($weather["temperature"], 1).$units["temp"]?></td>
  174.             <td nowrap><span class="bold">Dew point:</span> <?=round($weather["dewPoint"], 1).$units["temp"]?></td>
  175.             <td nowrap><span class="bold">Felt temperature:</span> <?=round($weather["feltTemperature"], 1).$units["temp"]?></td>
  176.             <td rowspan="4" valign="top">
  177.                 <span class="bold">Trend:</span><br>
  178. <?php
  179. if (isset($weather["trend"]) && sizeof($weather["trend"])) {
  180.     // Output the trends, loop through the arrays,
  181.     // convert the stuff to nice looking design, jadda, jadda...
  182.     foreach ($weather["trend"] as $trend) {
  183.         foreach ($trend as $key => $val) {
  184.             switch ($key) {
  185.                 case "type":
  186.                     switch ($val) {
  187.                         case "NOSIG":
  188.                             $string = "No Significant Weather";
  189.                             break;
  190.                         case "TEMPO":
  191.                             $string = "Temporary Weather";
  192.                             break;
  193.                         case "BECMG":
  194.                             $string = "Weather Becoming";
  195.                             break;
  196.                     }
  197.                     $value  = "";
  198.                     foreach (array("from", "to", "at") as $time) {
  199.                         if (isset($trend[$time])) {
  200.                             $value .= " ".$time." ".$trend[$time];
  201.                         }
  202.                     }
  203.                     ($value != "") ? $value  = trim($value).":":"";
  204.                     $string = '<span class="italic">'.$string.'</span>';
  205.                     $value  = '<span class="italic">'.$value.'</span>';
  206.                     break;
  207.                 case "wind":
  208.                     $string = "Wind:";
  209.                     $value  = (strtolower($trend["windDirection"]) == "calm") ? "Calm" : "From the ".$trend["windDirection"]." (".$trend["windDegrees"]."°) at ".round($trend["wind"], 1).$units["wind"];
  210.                     if (isset($trend["windVariability"])) {
  211.                         $value .= ", variable from ".$trend["windVariability"]["from"]."° to ".$trend["windVariability"]["to"]."°";
  212.                     }
  213.                     if (isset($trend["windGust"])) {
  214.                         $value .= ", with gusts up to ".round($trend["windGust"], 1).$units["wind"];
  215.                     }
  216.                     break;
  217.                 case "visibility":
  218.                     $string = "Visibility:";
  219.                     $value  = strtolower($trend["visQualifier"])." ".round($trend["visibility"], 1).$units["vis"];
  220.                     break;
  221.                 case "clouds":
  222.                     $string = "Clouds:";
  223.                     $value  = "";
  224.                     for ($i = 0; $i < sizeof($val); $i++) {
  225.                         $cloud = ucwords($val[$i]["amount"]);
  226.                         if (isset($val[$i]["type"])) {
  227.                             $cloud .= " ".$val[$i]["type"];
  228.                         }
  229.                         if (isset($val[$i]["height"])) {
  230.                             $cloud .= " at ".$val[$i]["height"].$units["height"];
  231.                         }
  232.                         $value .= $cloud." ";
  233.                     }
  234.                     break;
  235.                 case "condition":
  236.                     $string = "Condition:";
  237.                     $value  = ucwords($val);
  238.                     break;
  239.                 case "pressure":
  240.                     $string = "Pressure:";
  241.                     $value  = round($val, 1).$units["pres"];
  242.                     break;
  243.                 case "from":
  244.                 case "to":
  245.                 case "at":
  246.                 case "windDirection":
  247.                 case "windDegrees":
  248.                 case "windVariability":
  249.                 case "windGust":
  250.                 case "visQualifier":
  251.                     continue(2);
  252.                     break;
  253.                 default:
  254.                     $string = ""; $value = "";
  255.                     var_dump($key, $val);
  256.                     break;
  257.             }
  258. ?>
  259.                 <?=$string?> <?=$value?><br>
  260. <?php
  261.         }
  262.  
  263.     }
  264. } else {
  265. ?>
  266.                 none<br>
  267. <?php
  268. }
  269. ?>
  270.                 <span class="bold">Remarks:</span><br>
  271. <?php
  272. if (isset($weather["remark"]) && sizeof($weather["remark"])) {
  273.     // Same for the remarks, even less spectacular...
  274.     foreach($weather["remark"] as $key => $val) {
  275.         switch ($key) {
  276.             case "autostation":
  277.             case "presschg":
  278.             case "nospeci":
  279.             case "sunduration":
  280.             case "maintain":
  281.                 $string = "";
  282.                 $value  = $val;
  283.                 break;
  284.             case "seapressure":
  285.                 $string = "Pressure at sealevel:";
  286.                 $value  = round($val, 1).$units["pres"];
  287.                 break;
  288.             case "1htemp":
  289.                 $string = "Temperature for last hour:";
  290.                 $value  = round($val, 1).$units["temp"];
  291.                 break;
  292.             case "1hdew":
  293.                 $string = "Dew Point for last hour:";
  294.                 $value  = round($val, 1).$units["temp"];
  295.                 break;
  296.             case "6hmaxtemp":
  297.             case "6hmintemp":
  298.                 if (!isset($weather["remark"]["6hmaxtemp"]) && !isset($weather["remark"]["6hmintemp"])) {
  299.                     continue(2);
  300.                 }
  301.                 $string = "Max/Min Temp for last 6 hours:";
  302.                 $value  = (isset($weather["remark"]["6hmaxtemp"])) ? round($weather["remark"]["6hmaxtemp"], 1).$units["temp"] : "-";
  303.                 $value .= "/";
  304.                 $value .= (isset($weather["remark"]["6hmintemp"])) ? round($weather["remark"]["6hmintemp"], 1).$units["temp"] : "-";
  305.                 unset($weather["remark"]["6hmaxtemp"]); unset($weather["remark"]["6hmintemp"]);
  306.                 break;
  307.             case "24hmaxtemp":
  308.             case "24hmintemp":
  309.                 if (!isset($weather["remark"]["24hmaxtemp"]) && !isset($weather["remark"]["24hmintemp"])) {
  310.                     continue(2);
  311.                 }
  312.                 $string = "Max/Min Temp for last 24 hours:";
  313.                 $value  = (isset($weather["remark"]["24hmaxtemp"])) ? round($weather["remark"]["24hmaxtemp"], 1).$units["temp"] : "-";
  314.                 $value .= "/";
  315.                 $value .= (isset($weather["remark"]["24hmintemp"])) ? round($weather["remark"]["24hmintemp"], 1).$units["temp"] : "-";
  316.                 unset($weather["remark"]["24hmaxtemp"]); unset($weather["remark"]["24hmintemp"]);
  317.                 break;
  318.             case "snowdepth":
  319.                 $string = "Snow depth:";
  320.                 $value  = $val.$units["rain"];
  321.                 break;
  322.             case "snowequiv":
  323.                 $string = "Water equivalent of snow:";
  324.                 $value  = $val.$units["rain"];
  325.                 break;
  326.             case "sensors":
  327.                 $string = "";
  328.                 $value  = implode("<br>", $val);
  329.                 break;
  330.             default:
  331.                 $string = ""; $value = "";
  332.                 var_dump($key, $val);
  333.                 break;
  334.         }
  335. ?>
  336.                 <?=$string?> <?=$value?><br>
  337. <?php
  338.     }
  339. } else {
  340. ?>
  341.                 none<br>
  342. <?php
  343. }
  344. ?>
  345.             </td>
  346.         </tr>
  347.         <tr style="height: 15px">
  348.             <td colspan="2" style="width: 310px" nowrap><span class="bold">Pressure:</span> <?=round($weather["pressure"], 1).$units["pres"]?></td>
  349.             <td nowrap><span class="bold">Humidity:</span> <?=$weather["humidity"]?>%</td>
  350.         </tr>
  351.         <tr style="height: 15px">
  352.             <td colspan="2" nowrap>
  353.                 <span class="bold">Wind:</span> <?=strtolower($weather["windDirection"]) == "calm" ? "Calm" : "From the ".$weather["windDirection"]." (".$weather["windDegrees"]."°) at ".round($weather["wind"], 1).$units["wind"]?> 
  354.                 <?=isset($weather["windVariability"]) ? "<br>variable from ".$weather["windVariability"]["from"]."° to ".$weather["windVariability"]["to"]."°" : ""?> 
  355.                 <?=isset($weather["windGust"]) ? "<br>with gusts up to ".round($weather["windGust"], 1).$units["wind"] : ""?> 
  356.             </td>
  357.             <td valign="top" nowrap><span class="bold">Visibility:</span> <?=strtolower($weather["visQualifier"])?> <?=round($weather["visibility"], 1).$units["vis"]?></td>
  358.         </tr>
  359.         <tr>
  360.             <td colspan="2" valign="top">
  361.                 <span class="bold">Current condition:</span><br>
  362.                 <?=isset($weather["condition"]) ? ucwords($weather["condition"]) : "No Significant Weather"?> 
  363. <?php
  364. if (isset($weather["precipitation"]) && sizeof($weather["precipitation"])) {
  365.     // Output a line for each type of precipitation,
  366.     // distinguish between string and numeric values
  367. ?>
  368.                 <br><span class="bold">Precipitation:</span><br>
  369. <?php
  370.     for ($i = 0; $i < sizeof($weather["precipitation"]); $i++) {
  371.         $precip = "last ".$weather["precipitation"][$i]["hours"]."h: ".$weather["precipitation"][$i]["amount"];
  372.         $precip .= (ctype_alpha($weather["precipitation"][$i]["amount"])) ? "" : $units["rain"];
  373. ?>
  374.                 <?=$precip?><br>
  375. <?php
  376.     }
  377. }
  378. ?>
  379.             </td>
  380.             <td valign="top">
  381.                 <span class="bold">Clouds:</span><br>
  382. <?php
  383. if (isset($weather["clouds"]) && sizeof($weather["clouds"])) {
  384.     // Yeah, clouds... same as in the trend handling...
  385.     for ($i = 0; $i < sizeof($weather["clouds"]); $i++) {
  386.         $cloud = ucwords($weather["clouds"][$i]["amount"]);
  387.         if (isset($weather["clouds"][$i]["type"])) {
  388.             $cloud .= " ".$weather["clouds"][$i]["type"];
  389.         }
  390.         if (isset($weather["clouds"][$i]["height"])) {
  391.             $cloud .= " at ".$weather["clouds"][$i]["height"].$units["height"];
  392.         }
  393. ?>
  394.                 <?=$cloud?><br>
  395. <?php
  396.     }
  397. } else {
  398. ?>
  399.                 Clear Below <?=$metar->convertDistance(12000, "ft", $units["height"]).$units["height"]?> 
  400. <?php
  401. }
  402. ?>
  403.             </td>
  404.         </tr>
  405.         </table>
  406.     </td>
  407. </tr>
  408. <tr>
  409.     <td>
  410.         <table style="border-top: 2px solid #524b98; border-bottom: 2px solid #e0e3ce; border-left: 2px solid #b8b6c1; border-right: 2px solid #8b87a0; width: 100%">
  411.         <tr class="bgkhaki">
  412.             <td colspan="3" align="center" style="border-bottom: 2px solid #abada2"><span class="bold">Forecast (TAF)</span><br>valid from <span class="bold"><?=$forecast["validFrom"]?></span> to <span class="bold"><?=$forecast["validTo"]?></span></td>
  413.         </tr>
  414.         <tr valign="top">
  415.             <td colspan="3">
  416.                 <table style="width: 100%">
  417.                 <tr>
  418.                     <td align="center" class="bgkhaki" style="height: 15px; border-top: 2px solid #d8d8c0; border-right: 2px solid #8b87a0; border-left: 2px solid #d8d8c0"> </td>
  419.                     <td align="center" style="width: 18%"><span class="bold">Meteorological Conditions</span></td>
  420.                     <td align="center" style="width: 18%" class="bggrey"><span class="bold">Wind</span></td>
  421.                     <td align="center" style="width: 18%"><span class="bold">Visibility</span></td>
  422.                     <td align="center" style="width: 18%" class="bggrey"><span class="bold">Clouds</span></td>
  423.                     <td align="center" style="width: 18%"><span class="bold">Condition</span></td>
  424.                 </tr>
  425. <?php
  426. $times = array_keys($forecast["time"]);
  427. $pre   = array("wind" => 0, "vis" => 0, "clouds" => 0, "cond" => 0);
  428. // Ok, the forecast is a bit more interesting, as I'm taking a few
  429. // precautions here so that the table isn't filled up to the max.
  430. // o If a value is repeated in the next major timeslot (not when
  431. //   significant weather changes are processed), it's not printed
  432. // o Significant weather gets its own rows, with times printed normal
  433. //   as in opposition to bold print for major timeslots
  434. // o The while($row)-construct below is for handling the significant
  435. //   weather, as I point $row to $row["fmc"] afterwards, where the
  436. //   smaller changes are mentioned
  437. for ($i = 0; $i < sizeof($forecast["time"]); $i++) {
  438.     $row = $forecast["time"][$times[$i]];
  439.  
  440.     // Create timestamp
  441.     $start = $times[$i];
  442.     if ($i + 1 < sizeof($forecast["time"])) {
  443.         $end = $times[$i + 1];
  444.     } else {
  445.         $end = substr($forecast["validRaw"], -2).":00";
  446.         $end = ($end == "24:00") ? "00:00" : $end;
  447.     }
  448.     $time    = $start." - ".$end;
  449.     $class   = ' class="bold"';
  450.     // This is for outputting "Becoming", "Temporary" and such
  451.     $fmc     = isset($row["fmc"]) ? $row["fmc"] : false; 
  452.     $fmctype = "";
  453.     $fmccnt  = 0;
  454.  
  455.     while ($row) {
  456. ?>
  457.                 <tr class="bgkhaki">
  458.                     <td style="height: 1px; empty-cells: show; border-right: 2px solid #8b87a0; border-left: 2px solid #d8d8c0"></td>
  459.                     <td style="height: 1px" colspan="5"></td>
  460.                 </tr>
  461.                 <tr>
  462.                     <td align="center" class="bgkhaki" style="border-right: 2px solid #8b87a0; border-left: 2px solid #d8d8c0" nowrap><span<?=$class?>><?=$time?></span></td>
  463.                     <td align="center"><?=$fmctype?></td>
  464. <?php
  465.         // This loops through the available data and processes it
  466.         // for output, the different methods were already used above
  467.         // (Only difference is the checking for the pre-values.)
  468.         foreach(array("wind", "vis", "clouds", "cond") as $val) {
  469.             switch ($val) {
  470.                 case "wind":
  471.                     if (!isset($row["windDirection"])) {
  472.                         $string = " ";
  473.                     } else {
  474.                         $string = strtolower($row["windDirection"]) == "calm" ? "Calm" : "From the ".$row["windDirection"]." (".$row["windDegrees"]."°)<br>at ".round($row["wind"], 1).$units["wind"];
  475.                         if (isset($row["windProb"])) {
  476.                             $string .= " (".$row["windProb"]."% Prob.)";
  477.                         }
  478.                         if ($string === $pre["wind"]) {
  479.                             $string = " ";
  480.                         } else {
  481.                             $pre["wind"] = $string;
  482.                         }
  483.                     }
  484.                     $class = ' class="bggrey"';
  485.                     break;
  486.                 case "vis":
  487.                     if (!isset($row["visibility"])) {
  488.                         $string = " ";
  489.                     } else {
  490.                         $string = strtolower($row["visQualifier"])." ".round($row["visibility"], 1).$units["vis"];
  491.                         if (isset($row["visProb"])) {
  492.                             $string .= " (".$row["visProb"]."% Prob.)";
  493.                         }
  494.                         if ($string === $pre["vis"]) {
  495.                             $string = " ";
  496.                         } else {
  497.                             $pre["vis"] = $string;
  498.                         }
  499.                     }
  500.                     $class = '';
  501.                     break;
  502.                 case "clouds":
  503.                     if (!isset($row["clouds"])) {
  504.                         $string = " ";
  505.                     } else { 
  506.                         $clouds  = "";
  507.                         for ($j = 0; $j < sizeof($row["clouds"]); $j++) {
  508.                             $cloud = ucwords($row["clouds"][$j]["amount"]);
  509.                             if (isset($row["clouds"][$j]["type"])) {
  510.                                 $cloud .= " ".$row["clouds"][$j]["type"];
  511.                             }
  512.                             if (isset($row["clouds"][$j]["height"])) {
  513.                                 $cloud .= " at ".$row["clouds"][$j]["height"].$units["height"];
  514.                             }
  515.                             if (isset($row["clouds"][$j]["prob"])) {
  516.                                 $cloud .= " (".$row["clouds"][$j]["prob"]."% Prob.)";
  517.                             }
  518.                             $clouds .= $cloud."<br>";
  519.                         }
  520.                         if ($clouds === $pre["clouds"]) {
  521.                             $string = " ";
  522.                         } else {
  523.                             $string        = $clouds;
  524.                             $pre["clouds"] = $clouds;
  525.                         }
  526.                     }
  527.                     $class = ' class="bggrey"';
  528.                     break;
  529.                 case "cond":
  530.                     if (!isset($row["condition"]) || (isset($prerow) && $prerow["condition"] == $row["condition"])) {
  531.                         $string = " ";
  532.                     } else {
  533.                         $string = ucwords($row["condition"]);
  534.                     }
  535.                     $class = '';
  536.             }
  537. ?>
  538.                     <td valign="top"<?=$class?>><?=$string?></td>
  539. <?php
  540.         }
  541. ?>                    
  542.                 </tr>
  543. <?php
  544.         // Now check for significant weather changes and move
  545.         // the row accordingly... maybe ugly coding, but this
  546.         // is for showing design, not for fany programming ;-)
  547.         if ($fmc && $fmccnt < sizeof($fmc)) {
  548.             $row     = $fmc[$fmccnt];
  549.             $fmccnt++;
  550.             $fmctype = $row["type"];
  551.             // Check if we have a timestamp, don't output if it's
  552.             // the same as the major-timeslot
  553.             if (!isset($row["from"]) || $row["from"]." - ".$row["to"] == $time) {
  554.                 $time = " ";
  555.             } else {
  556.                 $time    = $row["from"]." - ".$row["to"];
  557.             }
  558.             switch ($row["type"]) {
  559.                 case "PROB":
  560.                     $fmctype = "";
  561.                     break;
  562.                 case "TEMPO":
  563.                     $fmctype = "Temporary";
  564.                     break;
  565.                 case "BECMG":
  566.                     $fmctype = "Becoming";
  567.                     break;
  568.             }
  569.             if (isset($row["probability"])) {
  570.                 $fmctype .= " (".$row["probability"]."% Prob.)";
  571.             }
  572.         } else {
  573.             $row = false;
  574.         }
  575.     }
  576. }
  577. ?>                
  578.                 <tr>
  579.                     <td class="bgkhaki" style="height: 1px; empty-cells: show; border-bottom: 2px solid #d8d8c0; border-left: 2px solid #d8d8c0; border-right: 2px solid #8b87a0"></td>
  580.                     <td style="height: 1px" colspan="5"></td>
  581.                 </tr>
  582.                 </table>
  583.             </td>
  584.         </tr>
  585.         <tr class="bgkhaki">
  586.             <td style="width: 93px; border-top: 2px solid #abada2"> </td>
  587.             <td style="border-top: 2px solid #abada2">Updated: (<?=substr($weather["update"], -5)?> / <?=substr($forecast["update"], -5)?>)</td>
  588.             <td style="border-top: 2px solid #abada2" align="right">All times UTC</td>
  589.         </tr>
  590.         </table>
  591.     </td>
  592. </tr>
  593. </table>
  594. <a href="javascript:history.back()">back</a>
  595. </body>
  596. </html>
  597.