#
# English: #
# OPTIONAL PARAMETERS: #
# uom= [ M | E] ............. set units-of-measure (M)etric or (E)glish #
# all= [ 0 | 1 ] ............ 1=show all elements on picture #
# wind= [ kts | mph | km/h | bft ] .. set uom for wind (also kph or m/s) #
# alti= [ ft | m ] ........... set uom for cloud altitude #
# rain= [ mm | in ] .......... set uom for rain #
# baro= [ hPa | kPa | inHg ] .. set uom for barometer #
# temp= [ C | F ] ............ set uom for temperature #
# humi= [ 0 | 1 ] ............ 1=show humidity #
# cond= [ 0 | 1 ] ............ 1=show conditions #
# cloud=[ 0 | 1 ] ............ 1=always show clouds when sunny or clear #
# metar=[ | empty ] ... get NOAA METAR for given code #
# data= [ en | de ] .......... language of data files ie. clientraw.txt #
# lang= [en | de | fi | nn | sv | es ] ... language to use. #
# test= [ 1..5 ] .............. use preset conditions for drawing picture #
# html= [ 0 | 1 ] ............. 1=output html code for testing, 0=save pic#
# PS: passing any of the above parameters will always override the #
# internal settings. #
# #
# FOR TESTING USE THE FOLLOWING: #
# http//www.mysite.com/cloud-base.php?uom=M&html=1 (current cond) #
# http//www.mysite.com/cloud-base.php?uom=M&html=1&test=1 (..test 1 to 5) #
# #
# CREDITS: #
# Please put the following snipped into your "wxabout.php" page: #
# Cloud base graphic courtesy of #
# Bashewa Weather #
################################################################################
# This script was inspired by Ken True's thermometer.php script. #
################################################################################
# This is also a plugin for the original website templates designed by: #
# Saratoga-Weather.org ... AJAX conditions display, dashboard & integration #
# (c) http://saratoga-weather.org/ #
# Ken True #
# TNET Services, Inc. ... PHP integration and website templates additions #
# (c) http://www.tnetweather.com/ #
# Kevin W. Reed #
# CarterLake.org ... original idea and template design #
# (c) http://www.carterlake.org/ #
# Tom #
################################################################################
# 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 #
################################################################################
# This document uses Tab 3 Settings #
################################################################################
# VERSION HISTORY: #
# 02 May 2009 V1.0 First release. #
# 02 May 2009 V1.1 Fixed translation issue for non-multilingual web sites. #
# 02 May 2009 V1.2 Added "dry" to the "clear,sunny" match string. #
# Added German match strings for German WD version. #
# 03 May 2009 V1.3 Added extra parameters for overriding specific UOM's. #
# Added $alwaysShowCloud when conditions are sunny or clear.#
# Added $windAlwaysMPH if wind should be in MPH for metric. #
# 03 May 2009 V1.4 Added $arrowColor for cloud height marker (arrow). #
# 03 May 2009 V1.5 Added ?all=1 parameter for showing all elements. #
# 04 May 2009 V1.6 Added $useMetarAtNight for determinig clouds at night. #
# Added $onlyUseMetar for determinig clouds at all times. #
# Fixed altitude and wind speed text overlap problem #
# Added $stationAltitude if you want to display ASL height. #
# 04 May 2009 V1.7 Added $useWDHeight for those who trust WD cloud height. #
# 05 May 2009 V1.8 Added language translations for de, es, fi, nn, sv. #
# Added OZZ METAR download from www.airservices.gov.au #
# Added code for WUHU software (Heavy Weather). #
# Fixed problem with METAR always being used in conditions. #
# 07 May 2009 V1.9 Added $showCloudTemp to show cloud temperature. #
# 05 Jan 2010 V2.0 Fixed Moon Phase problem. #
# 16 Jan 2011 V2.1 Fixed Moon Phase: Thanks, Ken True - Saratoga-weather.org #
# 14 May 2021 V2.2 Fixed curly brace deprecation w/PHP7 and WEEWX Ken True #
# 16 Jan 2022 V2.3 Fixed issues with PHP8 usage match->cloud_match Ken True #
# 01 Feb 2022 V2.4 Fixed PHP 8.1 Notice Errata Ken True #
################################################################################
$wxSoftware = 'WD'; // [ WD | VWS | WU ] ...set to 'VWS' to use VWS WeatherFlash files (overridden if specified in Settings.php)
// note: use 'WD' for WeeWX also as it generates the needed files
$DataLanguage= 'en'; // [ en | de ] ........language in the data file (i.e. clientraw.txt .. overridden by eg. ?data=en parameter)
$translateTo = 'en'; // [ en | de | es | fi | nn | sv ] ....language to be used on graphic (nn=Norwegian, sv=Swedish)
// ...... Leave language as "en" if you have the Saratoga World Multilingual templates that will do the translation for you.
#$Settings = './Settings.php'; // optional ...not required
#$WXtags = './testtags.php'; // for Weather-Display
#$WXtags = './WEEWXtags.php'; // for weewx-saratoga plugin to WeeWX
// optional ...not required (overridden if specified in Settings.php)
// Below are the tags used in testtags.php:
// ---------------------------------------------------------
// $marchequinox = '%marchequinox%'; // March equinox date (def 20Mar)
// $junesolstice = '%junesolstice%'; // June solstice date (def 21 Jun)
// $sepequinox = '%sepequinox%'; // September equinox date (def 22 Sep)
// $decsolstice = '%decsolstice%'; // December solstice date (def 21 Dec)
// $weatherreport = '%weatherreport%'; // METAR cloud report from WD
// ---------------------------------------------------------
// WD/WeeWX SETUP ONLY ... The below will be overridden by Settings.php if it's available
// WeeWX if used with weewx-saratoga plugin
$clientraw = './clientraw.txt'; // relative file address for WD clientraw.txt
#$clientraw = 'https://saratoga-weather.org/weewx/clientraw.php';
$clientextra = './clientrawextra.txt'; // relative file address for WD clientrawextra.txt
// VWS SETUP ONLY
// $wflashDir = './wflash/Data/'; // directory for the the VWS wflash.txt and wflash2.txt files (with trailing slash)
// WUHU SETUP ONLY (Heavy Weather)
// $WUHUdata = './currdat.lst'; // WUHU ini file
$tz = 'America/Los_Angeles'; // Timezone for sunrise / sunset (list at http://www.php.net/manual/en/timezones.php)
################################################################################
# begin settings #
################################################################################
$uom = 'E'; // [ M | E ] ...set to 'M' for metric, 'E' for imperial (overridden by testtags.php or by ?uom=M or ?uom=E parameter)
$useWDuom = false; // override $uom and use the same UOM values as in WD Console (requires testtags.php without uom's stripped if available)
$switchSeasons = true; // switch background according to seasons
$showCloudTemp = true; // show cloud temperature inside cloud
$showCaption = true; // include cloud type or precipitation at bottom of graphic (overridden by ?cond=1 parameter)
$showMoon = true; // include moon phase
$showScale = true; // include cloud height scale and marker
$showWinsock = true; // include the windsock (always set to true by "wind" parameter eg. ?wind=mph)
$showWindDir = true; // include wind direction below windsock (always set to true by "wind" parameter eg. ?wind=mph)
$showWindSpd = true; // include wind speed above windsock (always set to true by "wind" parameter eg. ?wind=mph)
$showTemp = true; // include temperature (always set to true by "temp" parameter eg. ?temp=F)
$showHumidity = true; // include humidity (overridden by "humi" parameter eg. ?humi=1)
$showBaro = false; // include barometric pressure (always set to true by "baro" parameter eg. ?baro=inHg)
$cloudsAlwaysFT = true; // cloudheight always in FT (if true will always overrides all other settings except if set by "alti" parameter eg. ?alti=m)
$windAlwaysMPH = true; // wind speed always in MPH (if true will always overrides all other settings except if set by "wind" parameter eg. ?wind=kts)
$alwaysShowCloud= false; // always show cloud band when condition is sunny, clear or dry (overridden by "cloud" parameter eg. ?cloud=1)
$useWDHeight = false; // always use the cloud height reported by WD (if you can trust it)
$arrowColor = '#FF0000'; // color for cloud height marker (arrow) ...white #FFFFFF, red #FF0000, green #FF0000, blue #0000FF
$getMetar = true; // get the METAR from NOAA for substituting cloud conditions at night and/or day (not required)
$metarICAO = "KSJC";// specify 4 letter ICAO code for METAR - NB: "Y..." METAR's will be fetched from OZZ (overridden if specified in Settings.php)
// Find a METAR closest to you here: http://www.bashewa.com/icao-codes.php
// Decode the METAR here: http://www.bashewa.com/metar-taf-decoder.php
$metarRefresh = 30; // refresh rate of the METAR in minutes
$useMetarAtNight= true; // always use METAR at night time for determinig clouds
$onlyUseMetar = false; // always use METAR for determinig clouds i.e. if you don't have a solar sensor or you don't trust WD's conditions
$reportMistAt = 30; // meters AGL (30m = ±90ft) ... if cloud base is below this then always report mist/fog
$stationAltitude= 0; // your station altitude in meters if you want cloud height reported above-sea-level (ASL)
// else cloud height will be reported above-ground-level (AGL) ... meters = ft / 3.2808399;
################################################################################
# optional settings from here onwards #
################################################################################
$pathToImages = './ajax-images/cb/'; // path to the background, cloud, windsock and scale images (with trailing slash)
$pathToMoonImages = './ajax-images/cb/moon/'; // path to the moon phase images (with trailing slash)
$fileOpenTries = 3; // number of open retries for clientraw/wflash files
$retrySleepTime = 3; // seconds to wait before next open retry
// Cutomised background settings ----------------------------------------------
// Specify your day and night backgrounds (numbers 01 to 33) ... not used if "$switchSeasons=true;" above
$bgDay = 'cb-bg-21d.png'; // Background image - Day
$bgNight = 'cb-bg-21n.png'; // Background image - Night
// Backgrounds for seasons switch (if "$switchSeasons=true;" above)
$bgSpringDay = 'cb-bg-00sprd.png'; // Background image - Spring - Day
$bgSpringNight = 'cb-bg-00sprn.png'; // Background image - Spring - Night
$bgSummerDay = 'cb-bg-00sumd.png'; // Background image - Summer - Day
$bgSummerNight = 'cb-bg-00sumn.png'; // Background image - Summer - Night
$bgAutumnDay = 'cb-bg-00autd.png'; // Background image - Autumn - Day
$bgAutumnNight = 'cb-bg-00autn.png'; // Background image - Autumn - Night
$bgWinterDay = 'cb-bg-00wind.png'; // Background image - Winter - Day
$bgWinterNight = 'cb-bg-00winn.png'; // Background image - Winter - Night
// Strings we can search for in the WD/VWS conditions for determining cloud type overlay (change with caution).
// You will have to translate them if WD reports the conditions in any other language other than English (or German).
// Look at your WD Solar/UV setup description for the actual strings or monitor your clientraw.txt conditions.
if ( isset($_GET["data"]) && !empty($_GET["data"]) ) $DataLanguage = trim($_GET["data"]);
if ($DataLanguage=='de') { // GERMAN WD VERSION
$sunny = 'klar,sonnig,trocken'; // for sunny
$partlycloudy = 'teilweise bewölkt,größtenteils klar,leicht bewölkt'; // for some clouds
$scattered = 'teilweise bewölkt'; // for clouds
$mostlycloudy = 'stark bewölkt,nach niederschlag'; // for many clouds
$overcast = 'geschlossene wolkendecke,bewölkt,vor kurzem niederschlag'; // for overcast
$thunderclouds = 'cumulonimbus,cumulus';
$drizzle = 'niesel';
$raining = 'regen,gewitterregen';
$snowing = 'es schneit,schnee';
$misty = 'nebel';
$rainstopped = 'vor kurtzem,nach niederschlag';
} else { // 'en' ... ENGLISH WD VERSION
$sunny = 'clear,sunny,dry'; // for sunny
$partlycloudy = 'partly,few,mostly clear'; // for some clouds
$scattered = 'scattered,broken'; // for clouds
$mostlycloudy = 'mostly cloudy,mainly,stopped raining'; // for many clouds
$overcast = 'cloudy,overcast,recent rain'; // for overcast
$thunderclouds = 'cumulonimbus,cumulus';
$drizzle = 'drizzle,shower';
$raining = 'rain,thunderstorm';
$snowing = 'snow,flurries';
$misty = 'mist,fog';
$rainstopped = 'recent rain,stopped raining,recent showers';
}
$precipitation = $raining.','.$snowing.','.$drizzle;
// Strings we can search for in NOAA METAR for determining cloud type overlay (change with caution)
$metSunny = 'SKC,CLR,NSC'; // for sunny
$metPartlycloudy = 'FEW'; // for some clouds (few = 1-2 octaves sky cover)
$metScattered = 'SCT'; // for clouds (sct = 3-4 octaves sky cover)
$metMostlycloudy = 'BKN'; // for many clouds (bkn = 5-7 octaves sky cover)
$metOvercast = 'OVC,RERN'; // for overcast (ovc = 8 octaves sky cover)
$metThunderclouds= 'CB,TCU,TS';
$metDrizzle = 'SHRA,DZ,-RA';
$metRaining = 'RA';
$metSnowing = 'SN,SG,GS';
$metMisty = 'BR,FG';
$metRainstopped = 'RERA';
$metPrecipitation= $metRaining.','.$metSnowing.','.$metDrizzle;
################################################################################
# end settings #
################################################################################
// ---------------------------------------------------------------------------//
// I M P O R T A N T //
// DO NOT customize the stuff below this point. //
// Everything is controlled by your settings above. //
// ---------------------------------------------------------------------------//
if (isset($_REQUEST['sce']) && ( strtolower($_REQUEST['sce']) == 'view' or
strtolower($_REQUEST['sce']) == 'show') ) {
//--self downloader --
$filenameReal = __FILE__;
$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;
}
################################################################################
# SETUP VALUES #
################################################################################
// for Saratoga language translations ... if available
if (file_exists("pws-translation.php")) {
include_once("pws-translation.php");
$translateCond = true;
}
// Cloud images (.png) and bottom of cloud pixel offsets ... do not alter
$imgMist = 'cb-cld-mist'; $imgMistBase = 86;
$imgScattered = 'cb-cld-scattered'; $imgScatteredBase = 50;
$imgPartly = 'cb-cld-partly'; $imgPartlyBase = 25;
$imgMostly = 'cb-cld-mostly'; $imgMostlyBase = 42;
$imgCloudy = 'cb-cld-cloudy'; $imgCloudyBase = 32;
$imgThunder = 'cb-cld-thunder'; $imgThunderBase = 60;
$imgShowers = 'cb-cld-showers'; $imgShowersBase = 25;
$imgRain = 'cb-cld-rain'; $imgRainBase = 32;
$imgThunderRain = 'cb-cld-thunder-rain'; $imgThunderRainBase = 60;
$imgSnow = 'cb-cld-snow'; $imgSnowBase = 32;
$imgCloudband = 'cb-cld-cloudband'; $imgCloudbandBase = 29;
if (!function_exists("gd_info"))
die("Sorry.. this script requires the GD2 library in PHP to function.");
// overrides from Settings.php if available
if (isset($Settings) and file_exists($Settings)) {
include_once($Settings);
if (isset($SITE['wxSoftware' ])) $wxSoftware = $SITE['wxSoftware'];
if (isset($SITE['clientrawfile' ])) $clientraw = $SITE['clientrawfile'];
if (isset($SITE['clientrawextrafile'])) $clientextra = $SITE['clientrawextrafile'];
if (isset($SITE['wflashdir' ])) $wflashDir = $SITE['wflashdir'];
if (isset($SITE['metarICAO' ])) $metarICAO = $SITE['metarICAO'];
if (isset($SITE['conditionsMETAR' ])) $metarICAO = $SITE['conditionsMETAR'];
if (isset($SITE['WXtags' ])) $WXtags = $SITE['WXtags'];
if (isset($SITE['tz' ])) $tz = $SITE['tz'];
}
if (!empty($tz)) {
if (phpversion() >= "5.1.0") date_default_timezone_set($tz);
else putenv("TZ=".$tz);
}
// Language settings for captions ----------------------------------------------
// will use language-??.txt files for translations if part of the Saratoga World Multilingual script templates
// otherwise if standalone then translate here (i.e. alter it here otherwise no need to)
if (isset($_GET['lang'])) $translateTo = strtolower(trim($_GET['lang']));
elseif (isset($_SESSION['lang'])) $translateTo = strtolower($_SESSION['lang']); // set by World Multilingual templates
$sunnyCap = 'Clear';
$partlycloudyCap = 'Partly cloudy';
$scatteredCap = 'Scattered';
$mostlycloudyCap = 'Mostly cloudy';
$overcastCap = 'Overcast';
$drizzleCap = 'Drizzle';
$rainingCap = 'Raining';
$snowingCap = 'Snowing';
$thunderstormCap = 'Thunderstorm';
$thundercloudsCap= 'Overcast';
$mistyCap = 'Misty';
if (isset($translateCond) && !empty($translateCond) && function_exists("langtransstr") && !isset($_GET['lang'])) {
$sunnyCap = langtransstr($sunnyCap);
$partlycloudyCap = langtransstr($partlycloudyCap);
$scatteredCap = langtransstr($scatteredCap);
$mostlycloudyCap = langtransstr($mostlycloudyCap);
$overcastCap = langtransstr($overcastCap);
$drizzleCap = langtransstr($drizzleCap);
$rainingCap = langtransstr($rainingCap);
$snowingCap = langtransstr($snowingCap);
$thunderstormCap = langtransstr($thunderstormCap);
$thundercloudsCap= langtransstr($thundercloudsCap);
$mistyCap = langtransstr($mistyCap);
} else
if ($translateTo=="de") {
$sunnyCap = 'Sonnig'; // for sunny
$partlycloudyCap = 'Leicht bewölkt'; // for some clouds
$scatteredCap = 'Teils bewölkt'; // for clouds
$mostlycloudyCap = 'Stark bewölkt'; // for many clouds
$overcastCap = 'Bewölkt'; // for overcast
$drizzleCap = 'Niesel';
$rainingCap = 'Es regnet';
$snowingCap = 'Es schneit';
$thunderstormCap = 'Gewitterregen';
$thundercloudsCap= 'Gewitterregen';
$mistyCap = 'Nebel';
} else
if ($translateTo=="es") {
$sunnyCap = 'Soleado'; // for sunny
$partlycloudyCap = 'Poco nuboso'; // for some clouds
$scatteredCap = 'Parcialmente nuboso'; // for clouds
$mostlycloudyCap = 'Muy nuboso'; // for many clouds
$overcastCap = 'Cubierto'; // for overcast
$drizzleCap = 'Lluvia débil';
$rainingCap = 'Lluvia';
$snowingCap = 'Nieve';
$thunderstormCap = 'Tormenta eléctrica';
$thundercloudsCap= 'Tormenta eléctrica';
$mistyCap = 'Niebla';
} else
if ($translateTo=="fi") {
$sunnyCap = 'Poutaa'; // for sunny
$partlycloudyCap = 'Vähäistä pilvisyyttä'; // for some clouds
$scatteredCap = 'Hajanaista pilvisyyttä'; // for clouds
$mostlycloudyCap = 'Runsasta pilvisyyttä'; // for many clouds
$overcastCap = 'Täysin pilvistä'; // for overcast
$drizzleCap = 'Tihkua';
$rainingCap = 'Sadetta';
$snowingCap = 'Lumisadetta';
$thunderstormCap = 'Ukkospilviä';
$thundercloudsCap= 'Ukkospilviä';
$mistyCap = 'Sumua';
} else
if ($translateTo=="nn" || $translateTo=="no") {
$sunnyCap = 'Skyfritt'; // for sunny
$partlycloudyCap = 'Lettskyet'; // for some clouds
$scatteredCap = 'Delvis skyet'; // for clouds
$mostlycloudyCap = 'Hovedsaklig skyet'; // for many clouds
$overcastCap = 'Overskyet'; // for overcast
$drizzleCap = 'Yr';
$rainingCap = 'Regn';
$snowingCap = 'Snør';
$thunderstormCap = 'Tordenvær';
$thundercloudsCap= 'Tordenvær';
$mistyCap = 'Tåke';
} else
if ($translateTo=="sv" || $translateTo=="se") {
$sunnyCap = 'Soligt'; // for sunny
$partlycloudyCap = 'Ett fåtal moln'; // for some clouds
$scatteredCap = 'Delvis molnigt'; // for clouds
$mostlycloudyCap = 'Övervägande molnigt'; // for many clouds
$overcastCap = 'Genommulet'; // for overcast
$drizzleCap = 'Duggregn';
$rainingCap = 'Regn';
$snowingCap = 'Snöat';
$thunderstormCap = 'Åska';
$thundercloudsCap= 'Åska';
$mistyCap = 'Dimma';
}
// Wind rose directions --------------------------------------------------------
// will use language-??.txt files for translations if part of the Saratoga World Multilingual script templates
// otherwise if standalone then translate here (i.e. alter it here otherwise no need to)
if ($translateTo=='de') { // German
$langWindDir = array(
"N", "NNO", "NO", "ONO",
"O", "OSO", "SO", "SSO",
"S", "SSW", "SW", "WSW",
"W", "WNW", "NW", "NNW");
} else
if ($translateTo=='es') { // Spanish
$langWindDir = array(
"N", "NNE", "NE", "ENE",
"E", "ESE", "SE", "SSE",
"S", "SSO", "SO", "OSO",
"O", "ONO", "NO", "NNO");
} else
if ($translateTo=='fi') { // Finnish
$langWindDir = array(
"P", "PKO", "KO", "IKO",
"I", "IKA", "KA", "EKA",
"E", "ELO", "LO", "LLO",
"L", "LLU", "LU", "PLU");
} else
if ($translateTo=='nn' || $translateTo=='no') { // Norwegian
$langWindDir = array(
"N", "NNØ", "NØ", "ØNØ",
"Ø", "ØSØ", "SØ", "SSØ",
"S", "SSV", "SV", "VSV",
"V", "VNV", "NV", "NNV");
} else
if ($translateTo=='sv' || $translateTo=='se') { // Swedish
$langWindDir = array(
"N", "NNO", "NO", "ONO",
"O", "OSO", "SO", "SSO",
"S", "SSV", "SV", "VSV",
"V", "VNV", "NV", "NNV");
} else { // English (default)
$langWindDir = array(
"N", "NNE", "NE", "ENE",
"E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW",
"W", "WNW", "NW", "NNW");
}
// set units of meaasure (overriden if testags.php is available and $useWDuom=true) ... do not alter
if (isset($_GET["uom"]) && (!empty($_GET["uom"]))) $uom = trim($_GET["uom"]);
if ($uom=='M') { // Metric
$uomTemp = 'C';
$uomRain = 'mm';
$uomWind = 'kmh';
$uomBaro = 'hPa';
$uomSnow = 'cm';
$uomAlt = 'm';
$uomDistance = 'km';
} else { // Imperial/English
$uomTemp = 'F';
$uomRain = 'in';
$uomWind = 'mph';
$uomBaro = 'inHg';
$uomSnow = 'in';
$uomAlt = 'ft';
$uomDistance = 'miles';
}
// determine and override the units of meassure from testtags.php if available (i.e. same as in WD setup)
if (isset($WXtags) and file_exists($WXtags)) {
include_once($WXtags);
if ($useWDuom && !isset($_GET["uom"])) { // set UOM same as in WD
$uomTemp = getUnits($temperature);
$uomWind = getUnits($avgspd);
$uomRain = getUnits($dayrn);
$uomBaro = getUnits($baro);
$uomBaro = ($uomBaro=='in'? 'inHg': $uomBaro);
$uom = ($uomTemp=='C' ? 'M' : 'E' );
$uomSnow = ($uom =='M' ? 'cm' : 'in' );
$uomAlt = ($uom =='M' ? 'm' : 'ft' );
$uomDistance = ($uom =='M' ? 'km' : 'miles' );
}
if ($switchSeasons) { // else we don't need this
if (!empty($marchequinox)) $marEquinox = strtotime($marchequinox);
if (!empty($junesolstice)) $junSolstice = strtotime($junesolstice);
if (!empty($sepequinox )) $sepEquinox = strtotime($sepequinox );
if (!empty($decsolstice )) $decSolstice = strtotime($decsolstice );
}
}
if ($cloudsAlwaysFT) $uomAlt = 'ft';
if ($windAlwaysMPH) $uomWind = 'mph';
// override the units of meassure if passed as a parameter
if (isset($_GET["all"]) && $_GET["all"]==1) {
$showTemp = true;
$showWinsock = true;
$showWindSpd = true;
$showWindDir = true;
$showBaro = true;
$showCaption = true;
$showHumidity = true;
$showCaption = true;
}
if (isset($_GET["temp"])) { $uomTemp = getUnits($_GET["temp"]); } //$showTemp = true; }
if (isset($_GET["wind"])) { $uomWind = getUnits($_GET["wind"]); } //$showWindSpd = true; $showWindDir = true; $showWinsock = true; }
if (isset($_GET["baro"])) { $uomBaro = getUnits($_GET["baro"]); } //$showBaro = true; }
if (isset($_GET["rain"])) { $uomRain = getUnits($_GET["rain"]); } //$showCaption = true; }
if (isset($_GET["alti"])) { $uomAlt = getUnits($_GET["alti"]); }
if (isset($_GET["humi"])) { $showHumidity = $_GET["humi"]==1 ? true : false; }
if (isset($_GET["cond"])) { $showCaption = $_GET["cond"]==1 ? true : false; }
if (isset($_GET["metar"])) { $getMetar = empty($_GET["metar"]) ? false : true; $metarICAO = trim($_GET["metar"]); }
if (isset($_GET["cloud"])) { $alwaysShowCloud = $_GET["cloud"]==1 ? true : false; }
if ($uomRain=='mm') $decRain=0; else $decRain=2; // decimal point for rain
//--------------------------
// WD: Load the data file(s)
//--------------------------
if ($wxSoftware == 'WD') { // Get the Weather-Display clientraw data files
for ($i=$fileOpenTries; $i>0; $i--) {
$file = @file_get_contents($clientraw);
if ($file===false) sleep($retrySleepTime);
else break;
}
if (!$file) { noDataFiles('cb-bg-NCR.png'); }
$data = explode(" ",$file);
$curtemp = $data[4]; // in °C
$curhumi = $data[5];
$rain = $data[7]; // in mm for today
$mintemp = $data[47]; // in °C
$maxtemp = $data[46]; // in °C
$icon = $data[48];
$curcond = str_replace("_"," ",$data[49]);
$UV = $data[79]; // value of 255 = no UV
$lat = $data[160];
$lng = -($data[161]); // invert because in WD it's minus for EAST of GMT
$dewp = $data[72]; // in °C
$baro = $data[6]; // in hPa
$wind = $data[1]; // in kts
$winddir = $data[3]; // in degrees
$cldhgtWD= $data[73] / 3.2808399; // in feet ... convert to meters
switch ($icon) {
case 8: // heavy rain
case 12: // heavy rain - night
case 14: // rain - night
case 20: // moderate rain
case 21: // light rain
case 24: // sleet showers
case 35: // rain & windy
$curcond.= ', '.$raining;
break;
case 15: // showers - night
case 22: // showers
$curcond.= ', '.$drizzle;
break;
case 16: // snow - night
case 25: // snow
case 27: // snow showers
$curcond.= ', '.$snowing;
break;
case 29: // thunder showers
case 30: // thunder showers
$curcond.= ', '.$thunderclouds.', '.$raining;
break;
case 31: // thunderstorms
$curcond.= ', '.$thunderclouds;
break;
}
for ($i=$fileOpenTries; $i>0; $i--) {
$file = @file($clientextra);
if ($file===false) sleep($retrySleepTime);
else break;
}
if (!file_exists($clientextra)) noDataFiles('cb-bg-NCR.png');
$data = explode(" ",$file[0]);
$sunrise = $data[556];
$sunset = $data[557];
$moonrise = $data[558];
$moonset = $data[559];
$moonpic = getMoonPic(); // $data[561];
} // end Weather Display data
else
//---------------------------
// VWS: Load the data file(s)
//---------------------------
if ($wxSoftware == 'VWS') { // Get the VWS Weather Flash data files (layout at http://saratoga-weather.org/show-wflash.php)
$filename = "${wflashDir}wflash.txt";
for ($i=$fileOpenTries; $i>0; $i--) {
$file = @file($filename);
if ($file===false) sleep($retrySleepTime);
else break;
}
if (!file_exists($filename)) noDataFiles('cb-bg-NVWS.png');
$data = explode(",",$file[0]);
$curtemp = convFtoC($data[9]); // in °F
$curhumi = $data[7];
$rain = convINtoMM($data[11]); // in inches for today
$UV = $data[19];
$dewp = convFtoF($data[24]); // in °F
$baro = convINHGtoMB($data[25]); // in inHg
$filename = "${wflashDir}wflash2.txt";
for ($i=$fileOpenTries; $i>0; $i--) {
$file = @file($filename);
if ($file===false) sleep($retrySleepTime);
else break;
}
if (!file_exists($filename)) noDataFiles('cb-bg-NVWS.png');
$data = explode(",",$file[0]);
$winddir = $data[2]; // in deg (running average)
$wind = convMPHtoKTS($data[3]); // in mph (running average)
$mintemp = convFtoC($data[92]); // in °F
$maxtemp = convFtoC($data[36]); // in °F
$sunrise = $data[277];
$sunset = $data[278];
$moonrise = $data[279];
$moonset = $data[280];
$moonpic = getMoonPic(); // $data[261];
$lat = $data[285];
$lng = $data[284];
$curcond = nameCloudsFromMetar($data[288]); // METAR cloud conditions
} // end VWS Weather Flash data
else
//---------------------------
// WUHU: Load the data file .
//---------------------------
if ($wxSoftware == 'WU') { // Get the WUHU data
if (!file_exists($WUHUdata)) noDataFiles('cb-bg-NWUHU.png');
$data = parse_ini_file($WUHUdata,true); // load the settings
$curtemp = $data["outdoor_temperature"]["deg_C"];
$curhumi = $data["outdoor_humidity"]["percent"];
$curcond = nameCloudsFromMetar($data["WUHU"]["METAR_sky"].', '.$data["WUHU"]["METAR_weather"]); // eg. "BKN"
$rain = $data["rain_daily"]["mm"];
$rainRate= $data["hourly_rates_of_change"]["outdoor_rain1hr_rate_mm"];
switch (true) {
case ($rainRate > 5.0): $xtraCond = 'Heavy Rain';
case ($rainRate > 3.0): $xtraCond = 'Moderate Rain';
case ($rainRate > 0.0): $xtraCond = 'Light Rain';
}
if ($rainRate>0) $curcond.= ', Raining';
$weather = $data["WUHU"]["METAR_weather"]; // eg. "RA"
$icon = $data["weather_picture"]["number"]; // eg. "-1=not valid, 0=rain, 1=cloud, 2=sun"
$picture = $data["weather_text"]["weather_picture"]; // eg. "Rainy"
$dewp = $data["dewpoint"]["deg_C"];
$baro = $data["pressure_relative"]["hpa"];
$wind = $data["wind_speed"]["knt"];
$winddir = $data["wind_direction"]["deg"];
$cldhgtWD= 0; // no cloud height available .. we'll calculate it
$lat = $data["WUHU"]["CWOP_latitude"]/100;
$lng = $data["WUHU"]["CWOP_longitude"]/100;
$sunrise = date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $lng);
$sunset = date_sunset (time(), SUNFUNCS_RET_STRING, $lat, $lng);
$moonpic = getMoonPic();
$moonrise= 0; // not needed
$moonset = 0; // not needed
$weatherreport = '';
}
### END OF LOAD DATA ###########################################################
// determine if it's day or night
$today = time();
$sun_rise = strtotime($sunrise);
$sun_set = strtotime($sunset );
$night = ($today>$sun_rise && $today<$sun_set)? false : true;
// manipulate current conditions report
$metcond = null;
if ($getMetar) {
switch (substr($metarICAO,0,1)) {
case "Y": $metar = get_metar_OZZ(strtoupper($metarICAO)); break; // from OZZ
default : $metar = get_metar_NWS(strtoupper($metarICAO)); // from NOAA
}
if(($metar != null)
&& ($metar[0] > mktime(date("H")-4))) // if METAR is older than 4 hours it's stale ...$metar[0] contains unix timestamp of METAR
$metcond = $metar[1];
} else
if (!empty($weatherreport))
$curcond.= ', '.$weatherreport; // from testtags.php if available i.e. WD METAR
if ($metcond != null) {
if(($getMetar && $metarICAO!="" && $useMetarAtNight && $night)
|| ($getMetar && $metarICAO!="" && $onlyUseMetar))
$curcond = nameCloudsFromMetar($metcond);
}
// determine cloud height (in meters)
if ($useWDHeight && $cldhgtWD>0)
$cldhgt = $cldhgtWD;
else $cldhgt = max(0,($curtemp-$dewp)/0.00802)+$stationAltitude;
$cldtemp = -0.00984 * ($cldhgt - $stationAltitude) + $curtemp; // cloud temperature
if ($cldhgt<$reportMistAt)
$curcond = 'Misty, '.$curcond;
// for testing only (pass parameter ?test=n) where n=[1 to 5] ------------------
$curcond1 = 'Overcast/Heavy thunderstorm, cumulonimbus,cumulus';
$metcond1 = 'FAJS 200800Z 02005KT 350V070 9999 SCT045 15/12 Q1022 RETSRA NOSIG RMK CB TO NE';
$curcond2 = 'Overcast/Heavy rain, rain,thunderstorm';
$metcond2 = 'FAJS 200830Z 33006KT 9999 -RA FEW030 BKN040 16/14 Q1022 RESHRA NOSIG ';
$curcond3 = 'Scattered clouds';
$metcond3 = 'FAJS 200830Z 33006KT 9999 FEW030 BKN040 16/14 Q1022 NOSIG ';
$curcond4 = 'Snowing';
$metcond4 = '';
if (isset($_GET["test"]) && (!empty($_GET["test"]))) {
$test = trim($_GET["test"]);
if (isset($_GET["bg"]) && !empty($_GET["bg"])) $bg = trim($_GET["bg"]); // background image override (filename)
switch ($test) {
case 1: $curcond = $curcond3; $metcond = $metcond3; $cldhgt = 2138; $night = false;
$wind = 14.7;
$showWindDir = true;
$showWindSpd = true;
$showTemp = true;
$showHumidity = true;
$showBaro = true;
break;
case 2: $night = false; $curcond = $curcond1; $metcond = $metcon1; $cldhgt = 1367; if ($bg) $bgDay=$bg; break;
case 3: $night = true; $curcond = $curcond2; $metcond = $metcon2; $cldhgt = 900; $rain = 15.2; break;
case 4: $night = false; $curcond = 'Misty, ' .$curcond; $metcond=''; $cldhgt = 0; break;
case 5: $night = false; $curcond = 'Snowing, '.$curcond; $metcond=''; $cldhgt = 1147; if ($bg) $bgDay=$bg; break;
}
}
// end testing -----------------------------------------------------------------
// determine the background to use according to season (if enabled)
if ($switchSeasons) {
if (empty($marEquinox )) $marEquinox = mktime(0,0,0, 3,20); // approximately
if (empty($junSolstice)) $junSolstice = mktime(0,0,0, 6,21);
if (empty($sepEquinox )) $sepEquinox = mktime(0,0,0, 9,22);
if (empty($decSolstice)) $decSolstice = mktime(0,0,0,12,21);
switch (true) {
case ($today>$marEquinox && $today<=$junSolstice): $season = $lat>0? 'Spring' : 'Autumn'; break;
case ($today>$junSolstice && $today<=$sepEquinox ): $season = $lat>0? 'Summer' : 'Winter'; break;
case ($today>$sepEquinox && $today<=$decSolstice): $season = $lat>0? 'Autumn' : 'Spring'; break;
default : $season = $lat>0? 'Winter' : 'Summer'; break;
}
switch($season) {
case 'Spring': $bgDay = $bgSpringDay; $bgNight = $bgSpringNight; break;
case 'Summer': $bgDay = $bgSummerDay; $bgNight = $bgSummerNight; break;
case 'Autumn': $bgDay = $bgAutumnDay; $bgNight = $bgAutumnNight; break;
case 'Winter': $bgDay = $bgWinterDay; $bgNight = $bgWinterNight; break;
}
}
// determine the background to use according to the daytime
if ($night) $background = $bgNight;
else $background = $bgDay;
// convert values to required UOM's
if ($uomAlt =="ft" ) $cldhgt = convMtoFT ($cldhgt);
else $uomAlt = 'm';
if ($uomTemp =="F" ){$curtemp= convCtoF ($curtemp);
$cldtemp= convCtoF ($cldtemp); }
else $uomTemp= 'C';
if ($uomRain =="in" ) $rain = convMMtoIN ($rain);
else $uomRain= 'mm';
if ($uomWind =="bft" ) $wind = convKTStoBFT ($wind); else
if ($uomWind =="mph" ) $wind = convKTStoMPH ($wind); else
if ($uomWind =="kph" ) $wind = convKTStoKMH ($wind); else
if ($uomWind =="kmh" ) $wind = convKTStoKMH ($wind); else
if ($uomWind =="km/h") $wind = convKTStoKMH ($wind); else
if ($uomWind =="m/s" ) $wind = convKTStoMPS ($wind);
else $uomWind= 'kts';
if ($uomBaro =="inHg") $baro = round(convHPAtoINHG($baro),2); else
if ($uomBaro =="kPa" ) $baro = round(convHPAtoKPA ($baro),1);
else $baro = round($baro); $uomBaro= 'hPa';
################################################################################
# CREATE IMAGE #
################################################################################
$imgBackground = $imgMoon = $imgWindsock = $imgClouds = $imgScale = null;
// get the image overlay filenames
$scale = getScale($cldhgt, $uomAlt);
$clouds = getClouds($curcond, $metcond, $night);
$windsock = getWindSock($wind, $night);
if ($night)
$moon = getMoon($lat,$moonpic);
// open image: background
if (!empty($background)) {
$imgBackground = imagecreatefrompng($pathToImages.$background);
imageAlphaBlending($imgBackground, false);
imageSaveAlpha($imgBackground, true);
}
// open image: scale
if ($showScale && !empty($scale["pic"])) {
$imgScale = imagecreatefrompng($pathToImages.$scale["pic"]);
imageAlphaBlending($imgScale, false);
imageSaveAlpha($imgScale, true);
}
// open image: windsock
if ($showWinsock && !empty($windsock)) {
$imgWindsock = imagecreatefrompng($pathToImages.$windsock);
imageAlphaBlending($imgWindsock, false);
imageSaveAlpha($imgWindsock, true);
}
// open image: moon
if ($showMoon && !empty($moon)) {
$imgMoon = imagecreatefromgif($pathToMoonImages.$moon);
imageAlphaBlending($imgMoon, false);
imageSaveAlpha($imgMoon, true);
}
// open image: clouds
if (!empty($clouds["pic"])) {
$imgClouds = imagecreatefrompng($pathToImages.$clouds["pic"]);
imageAlphaBlending($imgClouds, false);
imageSaveAlpha($imgClouds, true);
if (cloud_match($imgMist,$clouds["pic"])) {
$pt = $cldhgt==0?200:170;
$cY = $pt - $clouds["base"] - round($cldhgt/$scale["step"]);;
} else {
$pt = 170 - round($cldhgt/$scale["step"]);
$cY = $pt - $clouds["base"];
}
}
// make a slate to draw on
$slate = imagecreatetruecolor(imagesx($imgBackground), imagesy($imgBackground));
// now do the image overlay copying
if ($imgBackground) imagecopy($slate, $imgBackground, 0, 0, 0, 0, imagesx($imgBackground), imagesy($imgBackground));
if ($imgMoon) imagecopy($slate, $imgMoon , 66, 5, 0, 0, imagesx($imgMoon) , imagesy($imgMoon));
if ($imgWindsock) imagecopy($slate, $imgWindsock , 64,146, 0, 0, imagesx($imgWindsock) , imagesy($imgWindsock));
if ($imgClouds) imagecopy($slate, $imgClouds , 0,$cY, 0, 0, imagesx($imgClouds) , imagesy($imgClouds));
if ($imgScale) imagecopy($slate, $imgScale , 0, 0, 0, 0, imagesx($imgScale) , imagesy($imgScale));
// allocate text colours
$arrow = imagecolorallocate($slate, hexdec('0x'.$arrowColor[1].$arrowColor[2])
, hexdec('0x'.$arrowColor[3].$arrowColor[4])
, hexdec('0x'.$arrowColor[5].$arrowColor[6]));
$white = imagecolorallocate($slate,255,255,255 );
$black = imagecolorallocate($slate, 0, 0, 0 );
$yellow = imagecolorallocate($slate,255,255, 0 );
$red = imagecolorallocate($slate,255, 0, 0 );
$blue = imagecolorallocate($slate, 0, 0,255 );
$green = imagecolorallocate($slate, 0,255, 0 );
// Add cloudheight marker (if there's a cloud)
if ($showScale && $imgClouds) {
$pt = 165 - round($cldhgt/$scale["step"]);
$values = array(
0, $pt, // Point 1 (x, y)
10, $pt+5, // Point 2 (x, y)
0, $pt+10, // Point 3 (x, y)
);
@imagefilledpolygon($slate, $values, 3, $arrow);
}
// Add cloud conditions text
if ($showCaption && !empty($clouds["cap"])) {
$txtC = $clouds["cap"];
$font = 3;
$sizC = strlen($txtC)*imagefontwidth($font);
if ($sizC > 94) {
$font = 1;
$sizC = strlen($txtC)*imagefontwidth($font);
}
if (($showTemp || $showHumidity || $showBaro) && $sizC > 70) $font=1;
if (!$showTemp && !$showHumidity && !$showBaro) $Y=184; else $Y=174;
if (!$showTemp && !$showHumidity && !$showBaro) $col=$white; else $col=$yellow;
imagestring ( $slate,$font, 3, $Y, $txtC, $col);
}
// determine text lenghts of alt, temp, hum, baro and wind text
$txtT = round($curtemp).'°'.$uomTemp;
$sizT = strlen($txtT)*imagefontwidth(3);
$txtH = round($curhumi).'%';
$sizH = strlen($txtH)*imagefontwidth(3);
$txtB = $baro;
$sizB = strlen($txtB)*imagefontwidth(3);
$sizS = (100-(3+$sizT+$sizH+$sizB+3))/2; // spacing between temp, hum and baro values
// Add temperature text
if ($showTemp) {
$sizT = $sizT+$sizS;
imagestring ( $slate, 3, 3, 185, $txtT, $white);
}
// Add humidity text
if ($showHumidity) {
$sizH = $sizH+$sizS;
imagestring ( $slate, 3, (integer)(3+$sizT), 185, $txtH, $white);
}
// Add baro text
if ($showBaro) {
imagestring ( $slate, 3, (integer)(3+$sizT+$sizH), 185, $txtB, $white);
}
// Add wind direction text
if ($showWindDir) {
$txtD = windDEGtoDIR($winddir);
if (function_exists("langtransstr"))
$txtD = langtransstr($txtD);
$sizD = strlen($txtD)*imagefontwidth(3);
imagestring ( $slate, 3, 86-round($sizD/2), 174, $txtD, $white);
}
// Add windspeed text
$sizW = 0;
if ($showWindSpd) {
$txtW = round($wind).$uomWind;
$sizW = strlen($txtW)*imagefontwidth(2);
imagestring ( $slate, 2, 84-round($sizW/2), 136, $txtW, $white);
}
// Add cloudheight text (if there's a cloud)
if ($imgClouds) {
$txtC = round($cldhgt).' '.$uomAlt;
$sizC = strlen($txtC)*imagefontwidth(2);
$y = 170 - round($cldhgt/$scale["step"]);
if ($y>124) $z = (round(60-$sizW)/2)-($sizC/2); else $z=32-($sizC/2);
if ($z<0) { $font=1; $color=$yellow; $z=1; }
else { $font=2; $color=$white; }
imagestring ( $slate, $font, 36+($z), min(162,$y), $txtC, $color);
if ($showCloudTemp) {
$txtC = round($cldtemp).'°'.$uomTemp;
$sizC = strlen($txtC)*imagefontwidth(1);
$y = 170 - round($cldhgt/$scale["step"]);
if ($y>138) $z = (round(60-$sizW)/2)-($sizC/2); else $z=32-($sizC/2);
if ($z<0) $z=1;
$font=1;
if ($night) $color=$yellow;
else $color=$black;
imagestring ( $slate, $font, 36+($z), min(162,$y)-10, $txtC, $color);
}
}
// destroy images to prevent memory leaks
if ($imgBackground) imagedestroy($imgBackground);
if ($imgMoon) imagedestroy($imgMoon);
if ($imgClouds) imagedestroy($imgClouds);
if ($imgWindsock) imagedestroy($imgWindsock);
if ($imgScale) imagedestroy($imgScale);
// Output the image
if (isset($_GET["html"])) { // for output testing ( if 0 then only save picture and return img tag )
imagejpeg($slate,"cb.jpeg",80);
echo '';
if ($_GET["html"]==1) {
echo '
Date/Time: '.date("r",$today).' ('.($night?'night':'day').')';
echo '
Conditions: '.$curcond;
if ($getMetar) echo '
METAR: '.$metar[1];
echo '
Cloud Alt: '.round($cldhgt).$uomAlt.' ('.($stationAltitude>0 || $useWDHeight? 'ASL' : 'AGL').')';
echo '
Sunrise: '.date("r",$sun_rise);
echo '
Sunset : '.date("r",$sun_set);
echo '
TZ: '.date_default_timezone_get().' (GMT'.(date("Z")>=0?'+':'-').(abs(date("Z"))/3600).' hours)';
echo '
BG: '.$background;
echo '
Moon age: '.getMoonAge();
}
} else { // direct feed
header('Content-Type: image/jpeg');
imagejpeg($slate,null,80);
}
imagedestroy($slate);
exit;
### E N D CREATE IMAGE #######################################################
################################################################################
# FUNCTIONS #
################################################################################
// Deterimine the units of meassure used
function getUnits ($data) {
preg_match('/(mm|cm|ft|mb|hPa|kPa|inHg|in|kts|m\/s|mph|kmh|kph|km\/h|bft|C|F|m)/i',$data,$t);
return $t[0];
}
// Convert temperatures [°C | °F]
function convFtoC($value) { return (($value-32) / 1.8); }
function convCtoF($value) { return (($value * 1.8)+32); }
// Convert pressure [ mb | hPa | kPa | inHg ] 0.0295333727
function convINHGtoHPA($value) { return ($value / 0.0295333727); }
function convHPAtoINHG($value) { return ($value * 0.0295333727); }
function convHPAtoKPA ($value) { return ($value * 0.1); }
function convHPAtoMB ($value) { return ($value); }
// Convert depths [mm | inch)
function convINtoMM($value) { return ($value / 0.0393700787); }
function convMMtoIN($value) { return ($value * 0.0393700787); }
// Convert depths [cm | inch]
function convINtoCM($value) { return ($value / 0.393700787); }
function convCMtoIN($value) { return ($value * 0.393700787); }
// Convert heights [ft | m]
function convFTtoM($value) { return ($value / 3.2808399); }
function convMtoFT($value) { return ($value * 3.2808399); }
// Convert wind speeds [ kts | kmh | mph | m/s | beaufort]
function convMPHtoKTS($value) { return ($value / 1.15077945); }
function convKTStoMPH($value) { return ($value * 1.15077945); }
function convKTStoKMH($value) { return ($value * 1.852 ); }
function convKTStoMPS($value) { return ($value * 0.51444444); }
function convKTStoBFT( $spd ) {
switch (true) {
case ($spd < 1): $val= 0; break; // Calm
case ($spd < 4): $val= 1; break; // Light air
case ($spd < 7): $val= 2; break; // Light breeze
case ($spd < 11): $val= 3; break; // Gentle breeze
case ($spd < 17): $val= 4; break; // Moderate breeze
case ($spd < 22): $val= 5; break; // Fresh breeze
case ($spd < 28): $val= 6; break; // Strong breeze
case ($spd < 34): $val= 7; break; // Near gale
case ($spd < 41): $val= 8; break; // Gale
case ($spd < 48): $val= 9; break; // Strong gale
case ($spd < 56): $val=10; break; // Storm
case ($spd < 64): $val=11; break; // Violent storm
case ($spd >=64): $val=12; break; // Hurricane
}
return $val;
}
function windDEGtoDIR ($winddir) {
global $langWindDir;
return $langWindDir[(integer)fmod((($winddir + 11) / 22.5),16 )]; // V2.3 notice errata fix
}
// Windsock overlay image
function getWindSock($wind, $night = false) {
if ($night) $n='n'; else $n='';
$spd = convKTStoKMH($wind);
switch (true) {
case ($spd < 3): $img = 'cb-ws0'.$n.'.png'; break; // Calm
case ($spd < 14): $img = 'cb-ws1'.$n.'.png'; break; // Light
case ($spd < 42): $img = 'cb-ws2'.$n.'.png'; break; // Moderate
case ($spd < 88): $img = 'cb-ws3'.$n.'.png'; break; // Strong
case ($spd >=88): $img = 'cb-ws4'.$n.'.png'; break; // Storm
}
return $img;
}
// Scale overlay image
function getScale($cldhgt, $uom="m") {
switch ($uom) {
case "m": if ($cldhgt>3000) $size = 4400;
else $size = 3300;
$u = 'M';
break;
default : if ($cldhgt>10000) $size = 14300;
else $size = 11000;
$u = 'E';
}
$step = $size/165;
return array("pic"=>'cb-scale-200-'.$u.$size.'.png', "step"=>$step);
}
// Moon overlay image
function getMoon ($lat = 0, $moonpic = 14) {
$img = ($lat>=0?'N':'S').'H-moon'.str_pad($moonpic,2,"0",STR_PAD_LEFT).'.gif';
return $img;
}
// Clouds overlay image
function getClouds($conditions, $metarcond, $night = false) {
global $wxSoftware, $rain, $decRain, $uomRain, $rainstopped, $getMetar
// search string metar string image cloud base px caption //
, $sunny , $metSunny , $sunnyCap
, $misty , $metMisty , $imgMist , $imgMistBase , $mistyCap
, $partlycloudy , $metPartlycloudy , $imgPartly , $imgPartlyBase , $partlycloudyCap
, $scattered , $metScattered , $imgScattered , $imgScatteredBase , $scatteredCap
, $mostlycloudy , $metMostlycloudy , $imgMostly , $imgMostlyBase , $mostlycloudyCap
, $overcast , $metOvercast , $imgCloudy , $imgCloudyBase , $overcastCap
, $thunderclouds , $metThunderclouds , $imgThunder , $imgThunderBase , $thundercloudsCap
, $drizzle , $metDrizzle , $imgShowers , $imgShowersBase , $drizzleCap
, $raining , $metRaining , $imgRain , $imgRainBase , $rainingCap
, $imgThunderRain, $imgThunderRainBase, $thunderstormCap
, $snowing , $metSnowing , $imgSnow , $imgSnowBase , $snowingCap
, $alwaysShowCloud , $imgCloudband , $imgCloudbandBase
, $useMetarAtNight;
if((cloud_match($thunderclouds,$conditions) || cloud_match($metThunderclouds,$metarcond))
&& cloud_match($raining ,$conditions)
&& !cloud_match($rainstopped ,$conditions)) { $pic=$imgThunderRain; $base=$imgThunderRainBase; $cap=$thunderstormCap; } else
if (cloud_match($drizzle ,$conditions)
&& !cloud_match($rainstopped ,$conditions)) { $pic=$imgShowers; $base=$imgShowersBase; $cap=$drizzleCap; } else
if (cloud_match($raining ,$conditions)
&& !cloud_match($rainstopped ,$conditions)) { $pic=$imgRain; $base=$imgRainBase; $cap=$rainingCap; } else
if (cloud_match($snowing ,$conditions)) { $pic=$imgSnow; $base=$imgSnowBase; $cap=$snowingCap; } else
if (cloud_match($misty ,$conditions)) { $pic=$imgMist; $base=$imgMistBase; $cap=$mistyCap; } else
if((cloud_match($overcast ,$conditions) && cloud_match($metThunderclouds,$metarcond))
|| cloud_match($thunderclouds,$conditions)) { $pic=$imgThunder; $base=$imgThunderBase; $cap=$thundercloudsCap; } else
if (cloud_match($mostlycloudy ,$conditions)) { $pic=$imgMostly; $base=$imgMostlyBase; $cap=$mostlycloudyCap; } else
if (cloud_match($partlycloudy ,$conditions)) { $pic=$imgPartly; $base=$imgPartlyBase; $cap=$partlycloudyCap; } else
if (cloud_match($scattered ,$conditions)) { $pic=$imgScattered; $base=$imgScatteredBase; $cap=$scatteredCap; } else
if (cloud_match($overcast ,$conditions)) { $pic=$imgCloudy; $base=$imgCloudyBase; $cap=$overcastCap; } else
if (cloud_match($sunny ,$conditions)
&& $alwaysShowCloud) { $pic=$imgCloudband; $base=$imgCloudbandBase; $cap=$sunnyCap; } else
if (cloud_match($sunny ,$conditions)) { $pic=null; $base=0; $cap=$sunnyCap; } else
if (!$getMetar
&& $wxSoftware!='VWS') { $pic=$imgCloudband; $base=$imgCloudbandBase; $cap=''; } else
// try the METAR if we could not determine cloud from WD conditions
if (cloud_match($metThunderclouds,$metarcond)
&& cloud_match($metRaining ,$metarcond)
&& !cloud_match($metRainstopped ,$metarcond)) { $pic=$imgThunderRain; $base=$imgThunderRainBase; $cap=$thunderstormCap; } else
if (cloud_match($metDrizzle ,$metarcond)
&& !cloud_match($metRainstopped ,$metarcond)) { $pic=$imgShowers; $base=$imgShowersBase; $cap=$drizzleCap; } else
if (cloud_match($metRaining ,$metarcond)
&& !cloud_match($metRainstopped ,$metarcond)) { $pic=$imgRain; $base=$imgRainBase; $cap=$rainingCap; } else
if (cloud_match($metSnowing ,$metarcond)) { $pic=$imgSnow; $base=$imgSnowBase; $cap=$snowingCap; } else
if (cloud_match($metThunderclouds,$metarcond)) { $pic=$imgThunder; $base=$imgThunderBase; $cap=$thundercloudsCap; } else
if (cloud_match($metMisty ,$metarcond)) { $pic=$imgMist; $base=$imgMistBase; $cap=$mistyCap; } else
if (cloud_match($metOvercast ,$metarcond)) { $pic=$imgCloudy; $base=$imgCloudyBase; $cap=$overcastCap; } else
if (cloud_match($metMostlycloudy ,$metarcond)) { $pic=$imgMostly; $base=$imgMostlyBase; $cap=$mostlycloudyCap; } else
if (cloud_match($metPartlycloudy ,$metarcond)) { $pic=$imgPartly; $base=$imgPartlyBase; $cap=$partlycloudyCap; } else
if (cloud_match($metScattered ,$metarcond)) { $pic=$imgScattered; $base=$imgScatteredBase; $cap=$scatteredCap; } else
if (cloud_match($metSunny ,$metarcond)
&& $alwaysShowCloud) { $pic=$imgCloudband; $base=$imgCloudbandBase; $cap=$sunnyCap; } else
if (cloud_match($metSunny ,$metarcond)) { $pic=null; $base=0; $cap=$sunnyCap; }
else { $pic=$imgCloudband; $base=$imgCloudbandBase; $cap='MC'; } // no conditions available
if ($pic==$imgShowers || $pic==$imgRain || $pic==$imgThunderRain)
$cap.= ' '.round($rain,$decRain).$uomRain;
if ($night) $n='-n'; else $n='';
$cld = array
("pic" => ($pic==null?'':$pic.$n.'.png')
,"cap" => $cap
,"base" => $base
);
return $cld;
}
// match function
function cloud_match($searchfor,$haystack) {
if (empty($searchfor) or empty($haystack)) return false;
$needles = explode(",",$searchfor);
foreach($needles as $needle) {
// $pos=stripos($haystack,trim($needle));
$pos=strpos(strtolower($haystack),strtolower(trim($needle))); // PHP4
if ($pos!==false) return true;
}
return false;
}
function nameCloudsFromMetar ($metar) {
global $sunnyCap, $scatteredCap, $mostlycloudyCap, $overcastCap, $thundercloudsCap, $mistyCap;
$S[]="SKC"; $R[]="Sunny";
$S[]="CLR"; $R[]="Sunny";
$S[]="NSC"; $R[]="Sunny";
$S[]="FEW"; $R[]="Scattered clouds";
$S[]="SCT"; $R[]="Scattered clouds";
$S[]="BKN"; $R[]="Mostly cloudy";
$S[]="OVC"; $R[]="Overcast";
$S[]="CB"; $R[]="Cumulonimbus clouds";
$S[]="TCU"; $R[]="Towering cumulus clouds";
$S[]="TS"; $R[]="Thunderstorm";
$S[]="BR"; $R[]="Misty";
$S[]="FG"; $R[]="Foggy";
preg_match_all('/(OVC)|(BKN)|(SCT)|(FEW)|(TCU)|(CB)|(SKC)|(CLR)|(NSC)/i',$metar,$t,PREG_PATTERN_ORDER);
if (empty($t[0])) $t[0][0] = 'CLR';
$match = implode(", ",$t[0]);
return str_replace($S,$R,$match);
}
// Get METAR from NOAA
function get_metar_NWS($icao) {
global $metarRefresh; // refresh rate in minutes
if (empty($icao)) return null;
$reload = true;
$metarFile = 'metar-'.$icao.'.txt';
$metarTime = 0;
if (file_exists($metarFile)) {
$metarTime = filemtime($metarFile);
$reloadTime = $metarTime+($metarRefresh*60);
$now = time();
if ($now<$reloadTime) { // get saved file
$metar = getTxtFile($metarFile);
$reload = false;
}
}
if ($reload) { // download METAR if copy is stale or missing
$rawfile = 'https://tgftp.nws.noaa.gov/data/observations/metar/stations/'.$icao.'.TXT';
$raw_metar = @file($rawfile);
if ($raw_metar===false) return null;
$metar[0] = strtotime($raw_metar[0].' UTC');
$metar[1] = preg_replace("/[\n\r]+/is",'',$raw_metar[1]); // strip linefeeds
saveTxtFile($metarFile,$metar);
if ($metar[0]==$metarTime) // to prevent reloading if not updated according to $metarRefresh rate
$metarTime = $metarTime+($metarRefresh*60);
else $metarTime = $metar[0];
touch($metarFile,$metarTime);
}
return($metar); // $metar[0]=time and $metar[1]=metar
}
function get_metar_OZZ ($icao) {
global $metarRefresh; // refresh rate in minutes
if (empty($icao)) return null;
$reload = true;
$metarFile = 'metar-'.$icao.'.txt';
$metarTime = 0;
if (file_exists($metarFile)) {
$metarTime = filemtime($metarFile);
$reloadTime = $metarTime+($metarRefresh*60);
$now = time();
if ($now<$reloadTime) { // get saved file
$metar = getTxtFile($metarFile);
$reload = false;
}
}
if ($reload) { // download METAR if copy is stale or missing
$rawfile = 'http://www.airservices.gov.au/brief/html.asp?/cgi-bin/avreq?met='.$icao;
$page = @file($rawfile);
if ($page===false) return null;
$page = preg_replace("/[\n\r]+/is",'',implode(" ",$page));
preg_match_all("/METAR.*(TTF.*|)(METAR|SPECI)(.*)(ATIS|TAF|<\/pre>)/ismU",$page, $matches);
if (empty($matches[3][0])) return null;
$raw_metar = preg_replace("/[ ]{1,}/", " ", trim($matches[3][0]));
$date = date("Y").'/'.date("m").'/'.substr($raw_metar,5,2).' '.substr($raw_metar,7,2).':'.substr($raw_metar,9,2).' UTC';
$metar[0] = strtotime($date.' UTC');
$metar[1] = preg_replace("/[\n\r]+/is",'',$raw_metar); // strip linefeeds
saveTxtFile($metarFile,$metar);
if ($metar[0]==$metarTime) // to prevent reloading if not updated according to $metarRefresh rate
$metarTime = $metarTime+($metarRefresh*60);
else $metarTime = $metar[0];
touch($metarFile,$metarTime);
}
return($metar); // $metar[0]=time and $metar[1]=metar
}
// Save array to textfile
function saveTxtFile($filename, $lines = null) {
if (!empty($lines)) {
if(!file_exists($filename)) touch($filename); // quickest way to create a file
$txtfile=@fopen($filename, "wb");
if($txtfile) {
if (is_array($lines)) {
foreach ($lines as $line)
fwrite($txtfile, "$line\r\n");
} else
fwrite($txtfile, "$lines");
fclose($txtfile);
}
}
}
// Load array from textfile
function getTxtFile($filename) {
if (file_exists($filename))
$lines = file($filename,FILE_IGNORE_NEW_LINES && FILE_SKIP_EMPTY_LINES);
else $lines = '';
return $lines;
}
function noDataFiles($pic) {
global $pathToImages;
$img = imagecreatefrompng($pathToImages.$pic);
header('Content-Type: image/jpeg');
imagejpeg($img,null,70);
imagedestroy($img);
exit;
}
function getMoonInfo ($hh=0,$mm=0,$ss=0,$MM=0,$DD=0,$YY=0) { // very crude way of determining moon phase (but very accurate)
// ------------- start of USNO moon data -----------------------------
// PHP tables generated from USNO moon ephemeris data https://api.usno.navy.mil/moon/phase?date=1/1/yyyy&nump=60
// for years 2009 to 2030
// Ken True - Saratoga-weather.org generated by get-USNO-moonphases.php - Version 2.01 - 19-Apr-2019 on 19 April 2019 09:31 PDT
$newMoons = array( // unixtime values in UTC/GMT
/* 2009 */ /* 26-Jan-2009 07:55 */ 1232956500, 1235525700, 1238083560, 1240629780, 1243167060, 1245699300, 1248230100, 1250762520, 1253299440, 1255843980, 1258398840, 1260964920,
/* 2010 */ /* 15-Jan-2010 07:11 */ 1263539460, 1266115860, 1268686860, 1271248140, 1273799040, 1276341300, 1278877200, 1281409680, 1283941800, 1286477040, 1289019120, 1291570560,
/* 2011 */ /* 04-Jan-2011 09:03 */ 1294131780, 1296700260, 1299271560, 1301841120, 1304405460, 1306962180, 1309510440, 1312051200, 1314587040, 1317121740, 1319658960, 1322201400, 1324749960,
/* 2012 */ /* 23-Jan-2012 07:39 */ 1327304340, 1329863700, 1332427020, 1334992680, 1337557620, 1340118120, 1342671840, 1345218840, 1347761460, 1350302520, 1352844480, 1355388120,
/* 2013 */ /* 11-Jan-2013 19:44 */ 1357933440, 1360480800, 1363031460, 1365586500, 1368145680, 1370706960, 1373267640, 1375825860, 1378380960, 1380933240, 1383483000, 1386030120,
/* 2014 */ /* 01-Jan-2014 11:14 */ 1388574840, 1391117880, 1393660800, 1396205100, 1398752040, 1401302400, 1403856480, 1406414520, 1408975980, 1411539240, 1414101420, 1416659520, 1419212160,
/* 2015 */ /* 20-Jan-2015 13:14 */ 1421759640, 1424303220, 1426844160, 1429383420, 1431922380, 1434463500, 1437009840, 1439563980, 1442126460, 1444694760, 1447264020, 1449829740,
/* 2016 */ /* 10-Jan-2016 01:30 */ 1452389400, 1454942340, 1457488440, 1460028240, 1462562940, 1465095600, 1467630060, 1470170640, 1472720580, 1475280660, 1477849080, 1480421880, 1482994380,
/* 2017 */ /* 28-Jan-2017 00:07 */ 1485562020, 1488121080, 1490669820, 1493208960, 1495741440, 1498271460, 1500803160, 1503340200, 1505885400, 1508440320, 1511005320, 1513578600,
/* 2018 */ /* 17-Jan-2018 02:17 */ 1516155420, 1518728700, 1521292320, 1523843820, 1526384880, 1528918980, 1531450080, 1533981480, 1536516060, 1539056820, 1541606520, 1544167200,
/* 2019 */ /* 06-Jan-2019 01:28 */ 1546738080, 1549314240, 1551888240, 1554454200, 1557009900, 1559556120, 1562094960, 1564629120, 1567161420, 1569695160, 1572233880, 1574780760, 1577337180,
/* 2020 */ /* 24-Jan-2020 21:42 */ 1579902120, 1582471920, 1585042080, 1587608760, 1590169140, 1592721660, 1595266380, 1597804920, 1600340400, 1602876660, 1605416820, 1607962560,
/* 2021 */ /* 13-Jan-2021 05:00 */ 1610514000, 1613070360, 1615630860, 1618194660, 1620759600, 1623322380, 1625879820, 1628430600, 1630975920, 1633518300, 1636060440, 1638603780,
/* 2022 */ /* 02-Jan-2022 18:33 */ 1641148380, 1643694360, 1646242500, 1648794240, 1651350480, 1653910200, 1656471120, 1659030900, 1661588220, 1664142840, 1666694940, 1669244220, 1671790620,
/* 2023 */ /* 21-Jan-2023 20:53 */ 1674334380, 1676876760, 1679419380, 1681963920, 1684511580, 1687063020, 1689618720, 1692178680, 1694742000, 1697306100, 1699867620, 1702423920,
/* 2024 */ /* 11-Jan-2024 11:57 */ 1704974220, 1707519540, 1710061200, 1712600460, 1715138520, 1717677480, 1720220220, 1722769980, 1725328500, 1727894940, 1730465220, 1733034060, 1735597620,
/* 2025 */ /* 29-Jan-2025 12:36 */ 1738154160, 1740703500, 1743245880, 1745782260, 1748314920, 1750847460, 1753384260, 1755929160, 1758484440, 1761049500, 1763621220, 1766194980,
/* 2026 */ /* 18-Jan-2026 19:52 */ 1768765920, 1771329660, 1773883380, 1776426720, 1778961660, 1781492040, 1784022180, 1786556220, 1789097220, 1791647400, 1794207720, 1796777520,
/* 2027 */ /* 07-Jan-2027 20:24 */ 1799353440, 1801929360, 1804498140, 1807055460, 1809601080, 1812138000, 1814670120, 1817201100, 1819734060, 1822271760, 1824816960, 1827372240, 1829938320,
/* 2028 */ /* 26-Jan-2028 15:12 */ 1832512320, 1835087820, 1837657860, 1840218420, 1842768960, 1845311220, 1847847720, 1850381040, 1852914240, 1855450620, 1857993480, 1860545160,
/* 2029 */ /* 14-Jan-2029 17:24 */ 1863105840, 1865673060, 1868242740, 1870810800, 1873374120, 1875930600, 1878479460, 1881021360, 1883558640, 1886094840, 1888633440, 1891176720,
/* 2030 */ /* 04-Jan-2030 02:49 */ 1893725340, 1896278820, 1898836440, 1901397720, 1903961520, 1906525260, 1909085640, 1911640260, 1914188820, 1916733240, 1919276220, 1921819560, 1924363920
); /* end of newMoons array */
$Q1Moons = array( // unixtime values in UTC/GMT
/* 2009 */ /* 02-Feb-2009 23:13 */ 1233616380, 1236152760, 1238682840, 1241210640, 1243740120, 1246274880, 1248818400, 1251373320, 1253940600, 1256517720, 1259098740, 1261676160,
/* 2010 */ /* 23-Jan-2010 10:53 */ 1264243980, 1266799320, 1269342000, 1271874000, 1274398980, 1276921740, 1279447800, 1281982440, 1284529800, 1287091620, 1289666340, 1292248740,
/* 2011 */ /* 12-Jan-2011 11:31 */ 1294831860, 1297408680, 1299973500, 1302523500, 1305059580, 1307585460, 1310106540, 1312628880, 1315157940, 1317698100, 1320251880, 1322819520,
/* 2012 */ /* 01-Jan-2012 06:15 */ 1325398500, 1327983000, 1330564860, 1333136460, 1335693420, 1338236160, 1340767800, 1343292960, 1345816440, 1348342860, 1350876720, 1353421860, 1355980740,
/* 2013 */ /* 18-Jan-2013 23:45 */ 1358552700, 1361133060, 1363714020, 1366288260, 1368851640, 1371403440, 1373944680, 1376477760, 1379005680, 1381532520, 1384063020, 1386601920,
/* 2014 */ /* 08-Jan-2014 03:39 */ 1389152340, 1391714520, 1394285220, 1396859460, 1399432500, 1402000740, 1404561540, 1407113400, 1409656260, 1412191980, 1414723680, 1417255560, 1419791460,
/* 2015 */ /* 27-Jan-2015 04:48 */ 1422334080, 1424884440, 1427442180, 1430006100, 1432574340, 1435143720, 1437710640, 1440271860, 1442825940, 1445373060, 1447914420, 1450451640,
/* 2016 */ /* 16-Jan-2016 23:26 */ 1452986760, 1455522360, 1458061380, 1460606340, 1463158920, 1465719000, 1468284720, 1470853260, 1473421740, 1475987580, 1478548260, 1481101380,
/* 2017 */ /* 05-Jan-2017 19:47 */ 1483645620, 1486181940, 1488713520, 1491244740, 1493779620, 1496320920, 1498870260, 1501428180, 1503994380, 1506567180, 1509142920, 1511715780, 1514280000,
/* 2018 */ /* 24-Jan-2018 22:20 */ 1516832400, 1519373340, 1521905700, 1524433560, 1526960940, 1529491860, 1532029920, 1534578480, 1537139700, 1539712920, 1542293640, 1544874540,
/* 2019 */ /* 14-Jan-2019 06:45 */ 1547448300, 1550010360, 1552559220, 1555095960, 1557623520, 1560146340, 1562669700, 1565199060, 1567739400, 1570294020, 1572862980, 1575442680,
/* 2020 */ /* 03-Jan-2020 04:45 */ 1578026700, 1580607720, 1583179020, 1585736460, 1588279080, 1590809400, 1593332160, 1595853120, 1598378280, 1600912500, 1603459380, 1606020300, 1608594060,
/* 2021 */ /* 20-Jan-2021 21:01 */ 1611176460, 1613760420, 1616337600, 1618901940, 1621451580, 1623988440, 1626516660, 1629040740, 1631565540, 1634095500, 1636634760, 1639186500,
/* 2022 */ /* 09-Jan-2022 18:11 */ 1641751860, 1644328200, 1646909100, 1649486880, 1652055660, 1654613280, 1657160040, 1659697560, 1662228480, 1664756040, 1667284620, 1669818960, 1672363200,
/* 2023 */ /* 28-Jan-2023 15:19 */ 1674919140, 1677485160, 1680057120, 1682630400, 1685200920, 1687765800, 1690322820, 1692871020, 1695411120, 1697945340, 1700477400, 1703011140,
/* 2024 */ /* 18-Jan-2024 03:52 */ 1705549920, 1708095660, 1710648660, 1713208380, 1715773680, 1718342280, 1720910940, 1723475940, 1726034700, 1728586500, 1731131700, 1733671560,
/* 2025 */ /* 06-Jan-2025 23:56 */ 1736207760, 1738742520, 1741278660, 1743819300, 1746366720, 1748922060, 1751484600, 1754052060, 1756621500, 1759190040, 1761754860, 1764313140, 1766862600,
/* 2026 */ /* 26-Jan-2026 04:47 */ 1769402820, 1771936020, 1774466280, 1776997920, 1779534660, 1782078900, 1784631900, 1787193960, 1789764240, 1792339920, 1794916080, 1797486120,
/* 2027 */ /* 15-Jan-2027 20:34 */ 1800045240, 1802591880, 1805127900, 1807656960, 1810183440, 1812711360, 1815244740, 1817787240, 1820341860, 1822909620, 1825488000, 1828070520,
/* 2028 */ /* 05-Jan-2028 01:40 */ 1830649200, 1833217800, 1835773320, 1838315700, 1840847160, 1843371360, 1845893400, 1848418800, 1850952960, 1853500200, 1856062380, 1858637640, 1861220700,
/* 2029 */ /* 22-Jan-2029 19:23 */ 1863804180, 1866381000, 1868945580, 1871495400, 1874031360, 1876557240, 1879078440, 1881600900, 1884130140, 1886670540, 1889224500, 1891792140,
/* 2030 */ /* 11-Jan-2030 14:06 */ 1894370760, 1896954540, 1899535620, 1902106620, 1904663460, 1907206560, 1909738920, 1912264980, 1914789300, 1917316560, 1919850960, 1922396220, 1924954560
); /* end of Q1Moons array */
$fullMoons = array( // unixtime values in UTC/GMT
/* 2009 */ /* 09-Feb-2009 14:49 */ 1234190940, 1236739080, 1239288960, 1241841660, 1244398320, 1246958460, 1249520100, 1252080180, 1254636600, 1257189240, 1259739000, 1262286780,
/* 2010 */ /* 30-Jan-2010 06:18 */ 1264832280, 1267375080, 1269915900, 1272457080, 1275001620, 1277551800, 1280108220, 1282669500, 1285233420, 1287797760, 1290360420, 1292919180,
/* 2011 */ /* 19-Jan-2011 21:21 */ 1295472060, 1298018160, 1300558200, 1303094640, 1305630540, 1308168840, 1310712000, 1313261820, 1315819620, 1318385160, 1320956160, 1323527760,
/* 2012 */ /* 09-Jan-2012 07:30 */ 1326094200, 1328651640, 1331199540, 1333739940, 1336275300, 1338808320, 1341341520, 1343878020, 1346421480, 1348975140, 1351540140, 1354113960, 1356690060,
/* 2013 */ /* 27-Jan-2013 04:38 */ 1359261480, 1361823960, 1364376420, 1366919820, 1369455900, 1371987120, 1374516900, 1377049500, 1379589180, 1382139480, 1384701360, 1387272480,
/* 2014 */ /* 16-Jan-2014 04:52 */ 1389847920, 1392421980, 1394989680, 1397547720, 1400094960, 1402632660, 1405164300, 1407694140, 1410226680, 1412765460, 1415312580, 1417868820,
/* 2015 */ /* 05-Jan-2015 04:53 */ 1420433580, 1423004940, 1425578700, 1428149100, 1430710920, 1433261940, 1435803600, 1438339380, 1440873300, 1443408600, 1445947500, 1448491440, 1451041860,
/* 2016 */ /* 24-Jan-2016 01:46 */ 1453599960, 1456165200, 1458734460, 1461302640, 1463865240, 1466420520, 1468968960, 1471512360, 1474052700, 1476591780, 1479131520, 1481673900,
/* 2017 */ /* 12-Jan-2017 11:34 */ 1484220840, 1486773180, 1489330440, 1491890880, 1494452520, 1497013800, 1499573220, 1502129460, 1504681380, 1507228800, 1509772980, 1512316020,
/* 2018 */ /* 02-Jan-2018 02:24 */ 1514859840, 1517405220, 1519951860, 1522499820, 1525049880, 1527603540, 1530161580, 1532722800, 1535284560, 1537843920, 1540399500, 1542951540, 1545500940,
/* 2019 */ /* 21-Jan-2019 05:16 */ 1548047760, 1550591580, 1553132580, 1555672320, 1558213860, 1560760260, 1563313080, 1565872140, 1568435580, 1571000880, 1573565640, 1576127520,
/* 2020 */ /* 10-Jan-2020 19:21 */ 1578684060, 1581233580, 1583776080, 1586313300, 1588848300, 1591384320, 1593924240, 1596470340, 1599024120, 1601586300, 1604155740, 1606728600, 1609298880,
/* 2021 */ /* 28-Jan-2021 19:16 */ 1611861360, 1614413820, 1616957280, 1619494260, 1622027640, 1624560000, 1627094220, 1629633720, 1632182100, 1634741820, 1637312220, 1639888500,
/* 2022 */ /* 17-Jan-2022 23:48 */ 1642463280, 1645030560, 1647587820, 1650135300, 1652674440, 1655207520, 1657737480, 1660268160, 1662803940, 1665348900, 1667905320, 1670472480,
/* 2023 */ /* 06-Jan-2023 23:08 */ 1673046480, 1675621680, 1678192800, 1680755640, 1683308040, 1685850120, 1688384340, 1690914720, 1693445700, 1695981420, 1698524640, 1701076560, 1703637180,
/* 2024 */ /* 25-Jan-2024 17:54 */ 1706205240, 1708777800, 1711350000, 1713916140, 1716472380, 1719018480, 1721557020, 1724091960, 1726626840, 1729164360, 1731706080, 1734253320,
/* 2025 */ /* 13-Jan-2025 22:27 */ 1736807220, 1739368380, 1741935300, 1744503720, 1747068960, 1749627840, 1752179820, 1754726100, 1757268540, 1759808820, 1762348740, 1764890040,
/* 2026 */ /* 03-Jan-2026 10:03 */ 1767434580, 1769983740, 1772537880, 1775095920, 1777656180, 1780217100, 1782777360, 1785335760, 1787890680, 1790441340, 1792987920, 1795531980, 1798075680,
/* 2027 */ /* 22-Jan-2027 12:17 */ 1800620220, 1803165780, 1805712240, 1808260020, 1810810740, 1813365840, 1815925500, 1818487740, 1821049380, 1823608020, 1826162760, 1828714140,
/* 2028 */ /* 12-Jan-2028 04:03 */ 1831262580, 1833807840, 1836349560, 1838888760, 1841428140, 1843970940, 1846519860, 1849075800, 1851637620, 1854203100, 1856769420, 1859334000, 1861894080,
/* 2029 */ /* 30-Jan-2029 06:03 */ 1864447380, 1866993000, 1869531960, 1872067020, 1874601420, 1877138520, 1879680960, 1882230660, 1884788940, 1887355620, 1889928180, 1892501160,
/* 2030 */ /* 19-Jan-2030 15:54 */ 1895068440, 1897626000, 1900173360, 1902712800, 1905247140, 1907779260, 1910311920, 1912848240, 1915391880, 1917946020, 1920511800, 1923086400
); /* end of fullMoons array */
$Q3Moons = array( // unixtime values in UTC/GMT
/* 2009 */ /* 16-Feb-2009 21:37 */ 1234820220, 1237398420, 1239975360, 1242545160, 1245104100, 1247651580, 1250189700, 1252721760, 1255251360, 1257782160, 1260317580,
/* 2010 */ /* 07-Jan-2010 10:39 */ 1262860740, 1265413680, 1267976520, 1270546620, 1273119300, 1275689580, 1278254100, 1280811540, 1283361720, 1285905120, 1288442760, 1290976560, 1293509880,
/* 2011 */ /* 26-Jan-2011 12:57 */ 1296046620, 1298589960, 1301141220, 1303699620, 1306263120, 1308829680, 1311397320, 1313963640, 1316525940, 1319081400, 1321628940, 1324169280,
/* 2012 */ /* 16-Jan-2012 09:08 */ 1326704880, 1329239040, 1331774700, 1334314200, 1336859220, 1339411260, 1341971280, 1344538500, 1347110100, 1349681580, 1352248560, 1354807860,
/* 2013 */ /* 05-Jan-2013 03:58 */ 1357358280, 1359899760, 1362433980, 1364963820, 1367493240, 1370026680, 1372567980, 1375119780, 1377682500, 1380254100, 1382830800, 1385407680, 1387979280,
/* 2014 */ /* 24-Jan-2014 05:19 */ 1390540740, 1393089300, 1395625560, 1398153120, 1400677140, 1403203140, 1405735680, 1408278360, 1410833100, 1413400320, 1415978100, 1418561460,
/* 2015 */ /* 13-Jan-2015 09:46 */ 1421142360, 1423713000, 1426268880, 1428810240, 1431340560, 1433864520, 1436387040, 1438912980, 1441446840, 1443992760, 1446553440, 1449128400,
/* 2016 */ /* 02-Jan-2016 05:30 */ 1451712600, 1454297280, 1456873860, 1459437420, 1461986940, 1464523920, 1467051540, 1469574000, 1472096460, 1474624560, 1477163640, 1479717180, 1482285360,
/* 2017 */ /* 19-Jan-2017 22:13 */ 1484863980, 1487446380, 1490025480, 1492595820, 1495153980, 1497699180, 1500233160, 1502759700, 1505283900, 1507811100, 1510346160, 1512892260,
/* 2018 */ /* 08-Jan-2018 22:25 */ 1515450300, 1518018840, 1520594400, 1523171820, 1525745340, 1528309920, 1530863460, 1533406680, 1535942220, 1538473500, 1541004000, 1543537140, 1546076040,
/* 2019 */ /* 27-Jan-2019 21:10 */ 1548623400, 1551180480, 1553746200, 1556317080, 1558888440, 1561455960, 1564017480, 1566572160, 1569120060, 1571661540, 1574197860, 1576731420,
/* 2020 */ /* 17-Jan-2020 12:58 */ 1579265880, 1581805020, 1584351240, 1586904960, 1589464980, 1592029440, 1594596540, 1597164300, 1599729960, 1602290340, 1604843160, 1607387760,
/* 2021 */ /* 06-Jan-2021 09:37 */ 1609925820, 1612460220, 1614994200, 1617530520, 1620071400, 1622618640, 1625173860, 1627737360, 1630307580, 1632880620, 1635451500, 1638016080, 1640571840,
/* 2022 */ /* 25-Jan-2022 13:41 */ 1643118060, 1645655520, 1648186620, 1650714960, 1653244980, 1655781060, 1658326740, 1660883760, 1663451520, 1666026900, 1668605220, 1671180960,
/* 2023 */ /* 15-Jan-2023 02:10 */ 1673748600, 1676304060, 1678846080, 1681377060, 1683901680, 1686425460, 1688953680, 1691490480, 1694038860, 1696600080, 1699173420, 1701755340,
/* 2024 */ /* 04-Jan-2024 03:30 */ 1704339000, 1706915880, 1709479380, 1712027700, 1714562820, 1717089180, 1719611580, 1722135060, 1724664360, 1727203800, 1729756980, 1732325280, 1734905880,
/* 2025 */ /* 21-Jan-2025 20:31 */ 1737491460, 1740072720, 1742642940, 1745199300, 1747742340, 1750274340, 1752799080, 1755321120, 1757845980, 1760379180, 1762925280, 1765486320,
/* 2026 */ /* 10-Jan-2026 15:48 */ 1768060080, 1770640980, 1773221880, 1775796660, 1778361000, 1780912800, 1783452540, 1785982860, 1788508260, 1791033900, 1793564880, 1796105280, 1798657140,
/* 2027 */ /* 29-Jan-2027 10:55 */ 1801220100, 1803791760, 1806368040, 1808943480, 1811512680, 1814072040, 1816620900, 1819160820, 1821694800, 1824226140, 1826758080, 1829293860,
/* 2028 */ /* 18-Jan-2028 19:26 */ 1831836360, 1834387680, 1836948180, 1839515820, 1842086580, 1844656020, 1847220960, 1849779900, 1852332360, 1854878220, 1857417960, 1859953140,
/* 2029 */ /* 07-Jan-2029 13:26 */ 1862486760, 1865022720, 1867564260, 1870113060, 1872668880, 1875230340, 1877795820, 1880363700, 1882931580, 1885496220, 1888054320, 1890604080, 1893145740,
/* 2030 */ /* 26-Jan-2030 18:14 */ 1895681640, 1898215080, 1900749060, 1903286340, 1905829020, 1908379140, 1910938020, 1913505300, 1916078160, 1918651800, 1921221120, 1923782460
); /* end of Q3Moons array */
// ------------- end of USNO moon data -----------------------------
if ($hh==0) $hh=date("H");
if ($mm==0) $mm=date("i");
if ($ss==0) $ss=date("s");
if ($MM==0) $MM=date("m");
if ($DD==0) $DD=date("d");
if ($YY==0) $YY=date("Y");
$date = mktime($hh,$mm,$ss,$MM,$DD,$YY); // Unix date from local time
if ($date < $newMoons[1]) exit("Moon info date must be after " .date("r",$newMoons[1]).' (your date: '.date("r",$date[1]).')');
if ($date > $newMoons[count($newMoons)-1]) exit("Moon info date must be before ".date("r",$newMoons[count($newMoons)-1]).' (your date: '.date("r",$date[1]).')');
foreach ($newMoons as $mi=>$newMoon) // find next New Moon from given date
if ($newMoon>$date) break;
// Get Moon dates
$NM = $newMoons [$mi-1]; // previous new moon
$Q1 = $Q1Moons [$mi-1]; // 1st Q end
$Q2 = $fullMoons[$mi-1]; // 2nd Q end - Full moon
$Q3 = $Q3Moons [$mi-1]; // 3rd Q end
$Q4 = $newMoons [$mi ]; // 4th Q end - next new moon
// Divide each phase into 7 periods (4 phases x 7 = 28 periods)
$Q1p = round(($Q1-$NM)/7);
$Q2p = round(($Q2-$Q1)/7);
$Q3p = round(($Q3-$Q2)/7);
$Q4p = round(($Q4-$Q3)/7);
// Determine start and end times for major phases (lasting 1 period of 28)
$NMe = $NM+($Q1p/2); // 0% .... - New moon
$Q1s = $Q1-($Q1p/2); $Q1e = $Q1+($Q2p/2); // 50% 1stQ - First Quarter
$Q2s = $Q2-($Q2p/2); $Q2e = $Q2+($Q3p/2); //100% 2ndQ - Full moon
$Q3s = $Q3-($Q3p/2); $Q3e = $Q3+($Q4p/2); // 50% 3rdQ - Last Quarter
$NMs = $Q4-($Q4p/2); // 0% 4thQ - New Moon
// Determine age of moon in days since last new moon
$age = ($date - $newMoons[$mi-1])/86400; // age in days since last new moon
$dd = intval($age);
$hh = intval(($age-$dd)*24);
$mm = intval(((($age-$dd)*24)-$hh)*60);
$info = new STDclass;
$info->age = $dd.' days, '.$hh.' hours, '.$mm.' minutes ('.round($age,2).' days)';
// Deterime picture number (0-27) and moon phase
switch (true) {
case ($date<=$NMe): $pic = 0; break;
case ($date< $Q1s): $pic = 1 +(($date-$NMe)/$Q1p); break;
case ($date<=$Q1e): $pic = 7; break;
case ($date< $Q2s): $pic = 7.5+(($date-$Q1e)/$Q2p); break;
case ($date<=$Q2e): $pic = 14; break;
case ($date< $Q3s): $pic = 14.5+(($date-$Q2e)/$Q3p); break;
case ($date<=$Q3e): $pic = 21; break;
case ($date< $NMs): $pic = 21.5+(($date-$Q3e)/$Q4p); break;
default : $pic = 0;
}
$info->pic = round($pic);
return $info;
}
function getMoonAge() {
$mooninfo = getMoonInfo();
return $mooninfo->age;
}
function getMoonPic() {
$mooninfo = getMoonInfo();
return $mooninfo->pic;
}
function cleanupOldMoons() { // versions 2.0 only has 28 moon pictures 0-27 (not 30)
global $pathToMoonImages;
if (file_exists($pathToMoonImages."NH-moon29.gif")) {
unlink($pathToMoonImages."NH-moon15.gif");
unlink($pathToMoonImages."NH-moon29.gif");
for ($i=15; $i<28; $i++)
rename($pathToMoonImages."NH-moon".($i+1).".gif"
,$pathToMoonImages."NH-moon".($i ).".gif");
}
if (file_exists($pathToMoonImages."SH-moon29.gif")) {
unlink($pathToMoonImages."SH-moon15.gif");
unlink($pathToMoonImages."SH-moon29.gif");
for ($i=15; $i<28; $i++)
rename($pathToMoonImages."SH-moon".($i+1).".gif"
,$pathToMoonImages."SH-moon".($i ).".gif");
}
}
cleanupOldMoons();
################################################################################
# language-??.txt translations required if english (en) is not used. #
################################################################################
/*
conditions|begin||
# precipitation
langlookup|Dry|Dry|
langlookup|Drizzle|Drizzle|
langlookup|Light rain|Light rain|
langlookup|Moderate drizzle|Moderate drizzle|
langlookup|Moderate rain|Moderate rain|
langlookup|Heavy rain|Heavy rain|
langlookup|Stopped raining|Stopped raining|
langlookup|Recent rain|Recent rain|
langlookup|Snowing|Snowing|
langlookup|Raining|Raining|
langlookup|Thundershower|Thundershower|
langlookup|Thunderstorm|Thunderstorm|
langlookup|Heavy thunderstorm|Heavy thunderstorm|
# conditions time
langlookup|Dawn|Dawn|
langlookup|Dusk|Dusk|
langlookup|Night time|Night time|
langlookup|Night|Night|
# Clouds (sky)
langlookup|Fine weather|Fine weather|
langlookup|Clear|Clear|
langlookup|Sunny|Sunny|
langlookup|Clear skies|Clear skies|
langlookup|Mostly sunny|Mostly sunny|
langlookup|A few clouds|A few clouds|
langlookup|Sc|Partly cloudy|
langlookup|Scattered clouds|Scattered cloudy|
langlookup|Scattered|Scattered|
langlookup|Partly cloudy|Partly cloudy|
langlookup|Mostly cloudy|Mostly cloudy|
langlookup|Cloudy with clear patches|Mostly cloudy|
langlookup|Overcast|Overcast|
langlookup|Misty|Misty|
langlookup|Fog|Fog|
langlookup|Cloudbase|Cloudbase|
conditions|end||
*/
################################################################################
//... you must not have any spaces after this