and from output // heading=n - (default)='y' suppress printing of heading (forecast city/by/date) // icons=n - (default)='y' suppress printing of the icons+conditions+temp+wind+UV // text=n - (default)='y' suppress printing of the periods/forecast text // // // You can also invoke these options directly in the PHP like this // // $doIncludePW = true; // include("PW-forecast.php"); for just the text // or ------------ // $doPrintPW = false; // include("PW-forecast.php"); for setting up the $PWforecast... variables without printing // // or ------------ // $doIncludePW = true; // $doPrintConditions = true; // $doPrintHeadingPW = true; // $doPrintIconsPW = true; // $doPrintTextPW = false // include("PW-forecast.php"); include mode, print only heading and icon set // // Variables returned (useful for printing an icon or forecast or two...) // // $PWforecastcity - Name of city from PW Forecast header // // The following variables exist for $i=0 to $i= number of forecast periods minus 1 // a loop of for ($i=0;$i and Short legend. // $PWforecastwarnings = styled text with hotlinks to advisories/warnings // $PWcurrentConditions = table with current conds at point close to lat/long selected // // Settings --------------------------------------------------------------- // REQUIRED: a Pirateweather.net API KEY.. sign up at https://pirateweather.net $PWAPIkey = 'specify-for-standalone-use-here'; // use this only for standalone / non-template use // NOTE: if using the Saratoga template, add to Settings.php a line with: // $SITE['PWAPIkey'] = 'your-api-key-here'; // and that will enable the script to operate correctly in your template // $iconDir ='./forecast/images/'; // directory for carterlake icons './forecast/images/' $iconType = '.jpg'; // default type='.jpg' // use '.gif' for animated icons fromhttp://www.meteotreviglio.com/ // // The forecast(s) .. make sure the first entry is the default forecast location. // The contents will be replaced by $SITE['PWforecasts'] if specified in your Settings.php $PWforecasts = array( // Location|lat,long (separated by | characters) 'Saratoga, CA, USA|37.27465,-122.02295', 'Auckland, NZ|-36.910,174.771', // Awhitu, Waiuku New Zealand 'Assen, NL|53.02277,6.59037', 'Blankenburg, DE|51.8089941,10.9080649', 'Cheyenne, WY, USA|41.144259,-104.83497', 'Carcassonne, FR|43.2077801,2.2790407', 'Braniewo, PL|54.3793635,19.7853585', 'Omaha, NE, USA|41.19043,-96.13114', 'Johanngeorgenstadt, DE|50.439339,12.706085', 'Athens, GR|37.97830,23.715363', 'Haifa, IL|32.7996029,34.9467358', ); // $maxWidth = '640px'; // max width of tables (could be '100%') $maxIcons = 10; // max number of icons to display $maxForecasts = 14; // max number of Text forecast periods to display $maxForecastLegendWords = 4; // more words in forecast legend than this number will use our forecast words $numIconsInFoldedRow = 8; // if words cause overflow of $maxWidth pixels, then put this num of icons in rows $autoSetTemplate = true; // =true set icons based on wide/narrow template design $cacheFileDir = './'; // default cache file directory $cacheName = "PW-forecast-json.txt"; // locally cached page from PW $refetchSeconds = 3600; // cache lifetime (3600sec = 60 minutes) // // Units: // si: SI units (C,m/s,hPa,mm,km) // ca: same as si, except that windSpeed and windGust are in kilometers per hour // uk2: same as si, except that nearestStormDistance and visibility are in miles, and windSpeed and windGust in miles per hour // us: Imperial units (F,mph,inHg,in,miles) // $showUnitsAs = 'ca'; // ='us' for imperial, , ='si' for metric, ='ca' for canada, ='uk2' for UK // $charsetOutput = 'ISO-8859-1'; // default character encoding of output //$charsetOutput = 'UTF-8'; // for standalone use if desired $lang = 'en'; // default language $foldIconRow = false; // =true to display icons in rows of 5 if long texts are found $timeFormat = 'Y-m-d H:i T'; // default time display format $showConditions = true; // set to true to show current conditions box // ---- end of settings --------------------------------------------------- // overrides from Settings.php if available global $SITE; if (isset($SITE['PWforecasts'])) {$PWforecasts = $SITE['PWforecasts']; } if (isset($SITE['PWAPIkey'])) {$PWAPIkey = $SITE['PWAPIkey']; } // new V3.00 if (isset($SITE['PWshowUnitsAs'])) { $showUnitsAs = $SITE['PWshowUnitsAs']; } if (isset($SITE['fcsticonsdir'])) {$iconDir = $SITE['fcsticonsdir'];} if (isset($SITE['fcsticonstype'])) {$iconType = $SITE['fcsticonstype'];} if (isset($SITE['xlateCOP'])) {$xlateCOP = $SITE['xlateCOP'];} if (isset($LANGLOOKUP['Chance of precipitation'])) { $xlateCOP = $LANGLOOKUP['Chance of precipitation']; } if (isset($SITE['charset'])) {$charsetOutput = strtoupper($SITE['charset']); } if (isset($SITE['lang'])) {$lang = $SITE['lang'];} if (isset($SITE['cacheFileDir'])) {$cacheFileDir = $SITE['cacheFileDir']; } if (isset($SITE['foldIconRow'])) {$foldIconRow = $SITE['foldIconRow']; } if (isset($SITE['RTL-LANG'])) {$RTLlang = $SITE['RTL-LANG']; } if (isset($SITE['timeFormat'])) {$timeFormat = $SITE['timeFormat']; } if (isset($SITE['PWshowConditions'])) {$showConditions = $SITE['PWshowConditions'];} // new V1.05 // end of overrides from Settings.php // // -------------------begin code ------------------------------------------ $RTLlang = ',he,jp,cn,'; // languages that use right-to-left order if (isset($_REQUEST['sce']) && strtolower($_REQUEST['sce']) == 'view' ) { //--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; } $Status = "\n"; $PWcurrentConditions = ''; // HTML for table of current conditions //------------------------------------------------ if(preg_match('|specify|i',$PWAPIkey)) { print "

Note: the PW-forecast.php script requires an API key from Pirateweather.net to operate.
"; print "Visit pirateweather.net to "; print "register for an API key.

\n"; if( isset($SITE['fcsturlPW']) ) { print "

Insert in Settings.php an entry for:

\n"; print "\$SITE['PWAPIkey'] = 'your-key-here';

\n"; print "replacing your-key-here with your PW API key.

\n"; } return; } $NWSiconlist = array( // darksky.net ICON definitions 'clear-day' => 'skc.jpg', 'clear-night' => 'nskc.jpg', 'rain' => 'ra.jpg', 'snow' => 'sn.jpg', 'sleet' => 'fzra.jpg', 'wind' => 'wind.jpg', 'fog' => 'fg.jpg', 'cloudy' => 'ovc.jpg', 'partly-cloudy-day' => 'sct.jpg', 'partly-cloudy-night' => 'nsct.jpg', 'hail' => 'ip.jpg', 'thunderstorm' => 'tsra.jpg', 'tornado' => 'tor.jpg' ); // $windUnits = array( 'us' => 'mph', 'ca' => 'km/h', 'si' => 'm/s', 'uk2' => 'mph' ); $UnitsTab = array( 'si' => array('T'=>'°C','W'=>'m/s','P'=>'hPa','R'=>'mm','D'=>'km'), 'ca' => array('T'=>'°C','W'=>'km/s','P'=>'hPa','R'=>'mm','D'=>'km'), 'uk2' => array('T'=>'°C','W'=>'mph','P'=>'mb','R'=>'mm','D'=>'mi'), 'us' => array('T'=>'°F','W'=>'mph','P'=>'inHg','R'=>'in','D'=>'mi'), ); if(isset($UnitsTab[$showUnitsAs])) { $Units = $UnitsTab[$showUnitsAs]; } else { $Units = $UnitsTab['si']; } if(!function_exists('langtransstr')) { // shim function if not running in template set function langtransstr($input) { return($input); } } if(!function_exists('json_last_error')) { // shim function if not running PHP 5.3+ function json_last_error() { return('- N/A'); } $Status .= "\n"; if(!defined('JSON_ERROR_NONE')) { define('JSON_ERROR_NONE',0); } if(!defined('JSON_ERROR_DEPTH')) { define('JSON_ERROR_DEPTH',1); } if(!defined('JSON_ERROR_STATE_MISMATCH')) { define('JSON_ERROR_STATE_MISMATCH',2); } if(!defined('JSON_ERROR_CTRL_CHAR')) { define('JSON_ERROR_CTRL_CHAR',3); } if(!defined('JSON_ERROR_SYNTAX')) { define('JSON_ERROR_SYNTAX',4); } if(!defined('JSON_ERROR_UTF8')) { define('JSON_ERROR_UTF8',5); } } PW_loadLangDefaults (); // set up the language defaults $PWLANG = 'en'; // Default to English for API $lang = strtolower($lang); if( isset($PWlanguages[$lang]) ) { // if $lang is specified, use it $SITE['lang'] = $lang; $PWLANG = $PWlanguages[$lang]; $charsetOutput = (isset($PWlangCharsets[$lang]))?$PWlangCharsets[$lang]:$charsetOutput; } if(isset($_GET['lang']) and isset($PWlanguages[strtolower($_GET['lang'])]) ) { // template override $lang = strtolower($_GET['lang']); $SITE['lang'] = $lang; $PWLANG = $PWlanguages[$lang]; $charsetOutput = (isset($PWlangCharsets[$lang]))?$PWlangCharsets[$lang]:$charsetOutput; } $doRTL = (strpos($RTLlang,$lang) !== false)?true:false; // format RTL language in Right-to-left in output if(isset($SITE['copyr']) and $doRTL) { // running in a Saratoga template. Turn off $doRTL $Status .= "\n"; $doRTL = false; } if(isset($doShowConditions)) {$showConditions = $doShowConditions;} if($doRTL) {$RTLopt = ' style="direction: rtl;"'; } else {$RTLopt = '';}; // get the selected forecast location code $haveIndex = '0'; if (!empty($_GET['z']) && preg_match("/^[0-9]+$/i", htmlspecialchars($_GET['z']))) { $haveIndex = htmlspecialchars(strip_tags($_GET['z'])); // valid zone syntax from input } if(!isset($PWforecasts[0])) { // print "\n"; $PWforecasts = array("Saratoga|37.27465,-122.02295"); // create default entry } if(isset($useUTF8) and $useUTF8) { $charsetOutput = 'UTF-8'; $Status .= "\n"; } if($charsetOutput == 'UTF-8') { foreach ($PWlangCharsets as $l => $cs) { $PWlangCharsets[$l] = 'UTF-8'; } $Status .= "\n"; $Status .= "\n"; } if(stripos($timeFormat,'g') !== false or $showUnitsAs == 'us') { $showAMPMtime = true; $Status .= "\n"; } else { $showAMPMtime = false; $Status .= "\n"; } if(!headers_sent()) { header('Content-type: text/html,charset='.$charsetOutput); } // print "\n"; // Set the default zone. The first entry in the $SITE['NWSforecasts'] array. list($Nl,$Nn) = explode('|',$PWforecasts[0].'|||'); $FCSTlocation = $Nl; $PW_LATLONG = $Nn; if(!isset($PWforecasts[$haveIndex])) { $haveIndex = 0; } // locations added to the drop down menu and set selected zone values $dDownMenu = ''; for ($m=0;$m".langtransstr($Nlocation)."\n"; } // build the drop down menu $ddMenu = ''; // create menu if at least two locations are listed in the array if (isset($PWforecasts[0]) and isset($PWforecasts[1])) { $ddMenu .= '

'; } $Force = false; if (isset($_REQUEST['force']) and $_REQUEST['force']=="1" ) { $Force = true; } $doDebug = false; if (isset($_REQUEST['debug']) and strtolower($_REQUEST['debug'])=='y' ) { $doDebug = true; } $showTempsAs = ($showUnitsAs == 'us')? 'F':'C'; $Status .= "\n"; $fileName = "https://api.pirateweather.net/forecast/$PWAPIkey/$PW_LATLONG" . "?exclude=minutely&extend=hourly&units=$showUnitsAs"; if ($doDebug) { $Status .= "\n"; } if ($autoSetTemplate and isset($_SESSION['CSSwidescreen'])) { if($_SESSION['CSSwidescreen'] == true) { $maxWidth = '900px'; $maxIcons = 8; $maxForecasts = 8; $numIconsInFoldedRow = 7; $Status .= "\n"; } if($_SESSION['CSSwidescreen'] == false) { $maxWidth = '640px'; $maxIcons = 8; $maxForecasts = 8; $numIconsInFoldedRow = 7; $Status .= "\n"; } } $cacheName = $cacheFileDir . $cacheName; $cacheName = preg_replace('|\.txt|is',"-$haveIndex-$showUnitsAs.txt",$cacheName); // unique cache per units used.. all are in English $APIfileName = $fileName; if($showConditions) { $refetchSeconds = 15*60; // shorter refresh time so conditions will be 'current' } if (! $Force and file_exists($cacheName) and filemtime($cacheName) + $refetchSeconds > time()) { $html = implode('', file($cacheName)); $Status .= "\n"; } else { $Status .= "\n"; $html = PW_fetchUrlWithoutHanging($APIfileName,false); $RC = ''; if (preg_match("|^HTTP\/\S+ (.*)\r\n|",$html,$matches)) { $RC = trim($matches[1]); } $Status .= "\n"; if (preg_match('|30\d |',$RC)) { // handle possible blocked redirect preg_match('|Location: (\S+)|is',$html,$matches); if(isset($matches[1])) { $sURL = $matches[1]; if(preg_match('|opendns.com|i',$sURL)) { $Status .= "\n"; } else { $Status .= "\n"; $html = PW_fetchUrlWithoutHanging($sURL,false); $RC = ''; if (preg_match("|^HTTP\/\S+ (.*)\r\n|",$html,$matches)) { $RC = trim($matches[1]); } $Status .= "\n"; } } } if(preg_match('!temperature!is',$html)) { $fp = fopen($cacheName, "w"); if (!$fp) { $Status .= "\n"; } else { $write = fputs($fp, $html); fclose($fp); $Status .= "\n"; } } else { $Status .= "\n"; if(file_exists($cacheName) and filesize($cacheName) > 3000) { $html = implode('', file($cacheName)); $Status .= "\n"; } else { $Status .= "\n"; print $Status; print "

Sorry.. the Pirateweather forecast is not available.

\n"; return; } } } $charsetInput = 'UTF-8'; $doIconv = ($charsetInput == $charsetOutput)?false:true; // only do iconv() if sets are different if($charsetOutput == 'UTF-8') { $doIconv = false; } $Status .= "\n"; $tranTab = PW_loadTranslate($lang,$charsetOutput); $i = strpos($html,"\r\n\r\n"); $headers = substr($html,0,$i-1); $content = substr($html,$i+4); // process the file .. select out the 7-day forecast part of the page $UnSupported = false; // -------------------------------------------------------------------------------------------------- $Status .= "\n"; $i = strpos($html,"\r\n\r\n"); $headers = substr($html,0,$i-1); $content = substr($html,$i+4); $rawJSON = $content; $Status .= "\n"; $rawJSON = PW_prepareJSON($rawJSON); $JSON = json_decode($rawJSON,true); // get as associative array $Status .= PW_decode_JSON_error(); #if(isset($_GET['debug'])) {$Status .= "\n";} if(isset($JSON['daily']['data'][0]['time'])) { // got good JSON .. process it $UnSupported = false; $PWforecastcity = $FCSTlocation; if($doIconv) {$PWforecastcity = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWforecastcity);} if($doDebug) { $Status .= "\n"; } //$PWtitle = langtransstr("Forecast"); $PWtitle = $tranTab['Pirateweather Forecast for:']; if($doIconv) {$PWtitle = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWtitle);} if($doDebug) { $Status .= "\n"; } /* [daily] => Array ( [summary] => No precipitation throughout the week, with high temperatures bottoming out at 19°C on Thursday. [icon] => clear-day [data] => Array ( [0] => Array ( [time] => 1526886000 [summary] => Partly cloudy until afternoon. [icon] => partly-cloudy-day [sunriseTime] => 1526907369 [sunsetTime] => 1526958974 [moonPhase] => 0.23 [precipIntensity] => 0.0025 [precipIntensityMax] => 0.0432 [precipIntensityMaxTime] => 1526968800 [precipProbability] => 0.2 [precipType] => rain [temperatureHigh] => 18.87 [temperatureHighTime] => 1526936400 [temperatureLow] => 10.02 [temperatureLowTime] => 1526997600 [apparentTemperatureHigh] => 18.87 [apparentTemperatureHighTime] => 1526936400 [apparentTemperatureLow] => 10.02 [apparentTemperatureLowTime] => 1526997600 [dewPoint] => 9.38 [humidity] => 0.73 [pressure] => 1011.77 [windSpeed] => 3.04 [windGust] => 22.6 [windGustTime] => 1526943600 [windBearing] => 250 [cloudCover] => 0.41 [uvIndex] => 8 [uvIndexTime] => 1526932800 [visibility] => 15.21 [ozone] => 374.58 [temperatureMin] => 11.11 [temperatureMinTime] => 1526907600 [temperatureMax] => 18.87 [temperatureMaxTime] => 1526936400 [apparentTemperatureMin] => 11.11 [apparentTemperatureMinTime] => 1526907600 [apparentTemperatureMax] => 18.87 [apparentTemperatureMaxTime] => 1526936400 ) */ if(isset($JSON['timezone'])) { date_default_timezone_set($JSON['timezone']); $Status .= "\n"; } if(isset($JSON['daily']['data'][0]['time'])) { $PWupdated = $tranTab['Updated:']; if($doIconv) { $PWupdated = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWupdated). ' '; } if(isset($JSON['hourly']['data'][0]['time'])) { $PWupdated .= date($timeFormat,$JSON['hourly']['data'][0]['time']); } else { $PWupdated .= date($timeFormat,$JSON['daily']['data'][0]['time']); } } else { $PWupdated = ''; } if($doDebug) { $Status .= "\n\n"; } if(isset($windUnits[$showUnitsAs])) { $windUnit = $windUnits[$showUnitsAs]; $Status .= "\n"; if(isset($tranTab[$windUnit])) { $windUnit = $tranTab[$windUnit]; $Status .= "\n"; } } else { $windUnit = ''; } $n = 0; foreach ($JSON['daily']['data'] as $i => $FCpart) { # process each daily entry list($tDay,$tTime) = explode(" ",date('l H:i:s',$FCpart['time'])); if ($doDebug) { $Status .= "\n"; } $PWforecastdayname[$n] = $tDay; if(isset($tranTab[$tDay])) { $PWforecastday[$n] = $tranTab[$tDay]; } else { $PWforecastday[$n] = $tDay; } if($doIconv) { $PWforecastday[$n] = iconv("UTF-8",$charsetOutput.'//IGNORE',$PWforecastday[$n]); } $PWforecasttitles[$n] = $PWforecastday[$n]; if ($doDebug) { $Status .= "\n"; } $PWforecastcloudcover[$n] = $FCpart['cloudCover']; # extract the temperatures $PWforecasttemp[$n] = "".PW_round($FCpart['temperatureHigh'],0)."°$showTempsAs"; $PWforecasttemp[$n] .= "
".PW_round($FCpart['temperatureLow'],0)."°$showTempsAs"; # extract the icon to use $PWforecasticon[$n] = $FCpart['icon']; if ($doDebug) { $Status .= "\n"; } if(isset($FCpart['precipProbability'])) { $PWforecastpop[$n] = round($FCpart['precipProbability'],1)*100; } else { $PWforecastpop[$n] = 0; } if ($doDebug) { $Status .= "\n"; } if(isset($FCpart['precipType'])) { $PWforecastpreciptype[$n] = $FCpart['precipType']; } else { $PWforecastpreciptype[$n] = ''; } $PWforecasttext[$n] = // replace problematic characters in forecast text str_replace( array('<', '>', '–','cm.','in.','.)'), array('<','>','-', 'cm', 'in',')'), trim($FCpart['summary'])); $tstr = $PWforecasttext[$n]; $PWforecasttext[$n] = isset($tranTab[$tstr])?$tranTab[$tstr].'.':$tstr.'.'; # Add info to the forecast text if($PWforecastpop[$n] > 0) { $tstr = ''; if(!empty($PWforecastpreciptype[$n])) { $t = explode(',',$PWforecastpreciptype[$n].','); foreach ($t as $k => $ptype) { if(!empty($ptype)) {$tstr .= $tranTab[$ptype].',';} } if(strlen($tstr)>0) { $tstr = '('.substr($tstr,0,strlen($tstr)-1) .') '; } } $PWforecasttext[$n] .= " ". $tranTab['Chance of precipitation']." $tstr".$PWforecastpop[$n]."%. "; } $PWforecasttext[$n] .= " ".$tranTab['High:']." ".PW_round($FCpart['temperatureHigh'],0)."°$showTempsAs. "; $PWforecasttext[$n] .= " ".$tranTab['Low:']." ".PW_round($FCpart['temperatureLow'],0)."°$showTempsAs. "; $tWdir = PW_WindDir(round($FCpart['windBearing'],0)); $PWforecasttext[$n] .= " ".$tranTab['Wind']." ".PW_WindDirTrans($tWdir); $PWforecasttext[$n] .= " ". round($FCpart['windSpeed'],0)."->".round($FCpart['windGust'],0) . " $windUnit."; if(isset($FCpart['uvIndex']) and $FCpart['uvIndex'] > 1) { $PWforecasttext[$n] .= " ".$tranTab['UV index']." ".round($FCpart['uvIndex'],0)."."; } if($doIconv) { $PWforecasttext[$n] = iconv("UTF-8",$charsetOutput.'//IGNORE',$PWforecasttext[$n]); } if ($doDebug) { $Status .= "\n"; } //$temp = explode('.',$PWforecasttext[$n]); // split as sentences (sort of). $PWforecastcond[$n] = isset($tranTab[trim($FCpart['summary'])])? $tranTab[trim($FCpart['summary'])]:trim($FCpart['summary']); // take first one as summary. if($doIconv) { $PWforecastcond[$n] = iconv("UTF-8",$charsetOutput.'//IGNORE',$PWforecastcond[$n]); } if ($doDebug) { $Status .= "\n"; } $PWforecasticons[$n] = $PWforecastday[$n] . "
" . PW_img_replace( $PWforecasticon[$n],$PWforecastcond[$n],$PWforecastpop[$n],$PWforecastcloudcover[$n]) . "
" . $PWforecastcond[$n]; $n++; } // end of process text forecasts if(isset($JSON['flags']['sources'])) { $dsSources = PW_sources($JSON['flags']['sources']); // $Status .= "\n"; } // process alerts if any are available $PWforecastwarnings = ''; if (isset($JSON['alerts']) and is_array($JSON['alerts']) and count($JSON['alerts']) > 0) { $Status.= "\n"; foreach($JSON['alerts'] as $i => $ALERT) { $expireUTC = $ALERT['expires']; $expires = date($timeFormat,$ALERT['expires']); $Status.= "\n"; $regions = ''; $description = str_replace(' * ',"\n* ",$ALERT['description']); if(is_array($ALERT['regions'])) { foreach ($ALERT['regions'] as $i => $reg) { $regions .= $reg . ', '; } $regions = substr($regions,0,strlen($regions)-2); } if (time() < $expireUTC) { $PWforecastwarnings .= '' . '' . $ALERT['title'] . "
\n"; } else { $Status.= "\n"; } } } else { $Status.= "\n"; } // make the Current conditions table from $currently array $currently = $JSON['currently']; /* "currently": { "time": 1543970527, "summary": "Overcast", "icon": "cloudy", "nearestStormDistance": 0, "precipIntensity": 0.127, "precipIntensityError": 0.1016, "precipProbability": 0.21, "precipType": "rain", "temperature": 12.35, "apparentTemperature": 12.35, "dewPoint": 5.48, "humidity": 0.63, "pressure": 1013.59, "windSpeed": 5.89, "windGust": 15.61, "windBearing": 102, "cloudCover": 1, "uvIndex": 0, "visibility": 14.89, "ozone": 311.96 }, "daily": { "summary": "Light rain today through Monday, with high temperatures rising to 16°C on Thursday.", "icon": "rain", */ $nCols = 3; // number of columns in the conditions table if (isset($currently['time']) ) { // only generate if we have the data if (isset($currently['icon']) and ! $currently['icon'] ) { $nCols = 2; }; $PWcurrentConditions = '' . "\n"; $PWcurrentConditions .= ' ' . "\n\n"; if (isset($currently['icon'])) { $tCond = isset($tranTab[$currently['summary']])?$tranTab[$currently['summary']]:$currently['summary']; $PWcurrentConditions .= ' '; } // end of icon $PWcurrentConditions .= " '; $PWcurrentConditions .= ' '; if(isset($JSON['daily']['summary'])) { $tCond = isset($tranTab[$JSON['daily']['summary']])?$tranTab[$JSON['daily']['summary']]:$JSON['daily']['summary']; if($doRTL) { $PWcurrentConditions .= ' '; } else { $PWcurrentConditions .= ' '; } } $PWcurrentConditions .= '
' . $tranTab['Currently'].': '. date($timeFormat,$currently['time']) . "
\n"; # removed V2.02 - nearest-station is always zero # $t = $tranTab['Weather conditions at 999 from forecast point.']; # $t = str_replace('999',round($JSON['flags']['nearest-station'],1).' '.$Units['D'],$t); $PWcurrentConditions .= '
' . PW_img_replace( $currently['icon'], $tCond, round($currently['precipProbability'],1)*100, $currently['cloudCover']) . "
\n" . $tCond; $PWcurrentConditions .= '
\n"; if (isset($currently['temperature'])) { $PWcurrentConditions .= $tranTab['Temperature'].": ". PW_round($currently['temperature'],0) . $Units['T'] . "
\n"; } if (isset($currently['windchill'])) { $PWcurrentConditions .= $tranTab['Wind chill'].": ". PW_round($currently['windchill'],0) . $Units['T']. "
\n"; } if (isset($currently['heatindex'])) { $PWcurrentConditions .= $tranTab['Heat index'].": " . PW_round($currently['heatindex']) . $Units['T']. "
\n"; } if (isset($currently['windSpeed'])) { $tWdir = PW_WindDir(round($currently['windBearing'],0)); $PWcurrentConditions .= $tranTab['Wind'].": ".PW_WindDirTrans($tWdir); $PWcurrentConditions .= " ".round($currently['windSpeed'],0). "->".round($currently['windGust'],0) . " $windUnit." . "
\n"; } if (isset($currently['humidity'])) { $PWcurrentConditions .= $tranTab['Humidity'].": ". round($currently['humidity'],1)*100 . "%
\n"; } if (isset($currently['dewPoint'])) { $PWcurrentConditions .= $tranTab['Dew Point'].": ". PW_round($currently['dewPoint'],0) . $Units['T'] . "
\n"; } $PWcurrentConditions .= $tranTab['Barometer'].": ". PW_conv_baro($currently['pressure']) . " " . $Units['P'] . "
\n"; if (isset($currently['visibility'])) { $PWcurrentConditions .= $tranTab['Visibility'].": ". round($currently['visibility'],1) . " " . $Units['D']. "\n" ; } if (isset($currently['uvIndex'])) { $PWcurrentConditions .= '
'.$tranTab['UV index'].": ". round($currently['uvIndex'],0) . "\n" ; } $PWcurrentConditions .= '
'; $tFMT = ($showUnitsAs == 'us')?'g:ia':'H:i'; if(isset($JSON['daily']['data'][0]['sunriseTime']) and isset($JSON['daily']['data'][0]['sunsetTime']) ) { $PWcurrentConditions .= $tranTab['Sunrise'].': '. date($tFMT,$JSON['daily']['data'][0]['sunriseTime']) . "
\n" . $tranTab['Sunset'].': '. date($tFMT,$JSON['daily']['data'][0]['sunsetTime']) . "
\n" ; } $PWcurrentConditions .= '
' . $tCond . '
' . $tCond . '
'; if($doIconv) { $PWcurrentConditions = iconv('UTF-8',$charsetOutput.'//TRANSLIT',$PWcurrentConditions); } } // end of if isset($currently['cityobserved']) // end of current conditions mods $timelineColors = array( // timeline Colors to use for each condition "Clear" => "#eeeef5", "Partly Cloudy" => "#d5dae2", "Cloudy"=> "#b6bfcb", "Rain" => "#4a80c7", "Light Rain" => "#80a5d6", "Drizzle" => "#a4b8d4", "Snow" => "#8c82ce", "Light Snow" => "#aba4db", "Flurries"=> "#b7b2db", "Sleet"=> "#6264a7", "Fog" => "#d5dae2", "Wind" => "#ffdead", "Windy" => "#ffdead", ); if(isset($JSON['hourly']['data'][0]['time'])) { // process Hourly forecast data /* "hourly": { "summary": "Mostly cloudy throughout the day.", "icon": "partly-cloudy-night", "data": [{ "time": 1548018000, "summary": "Mostly Cloudy", "icon": "partly-cloudy-day", "precipIntensity": 0.1422, "precipProbability": 0.29, "precipType": "rain", "temperature": 14.91, "apparentTemperature": 14.91, "dewPoint": 11.49, "humidity": 0.8, "pressure": 1017.89, "windSpeed": 10.8, "windGust": 24.54, "windBearing": 226, "cloudCover": 0.88, "uvIndex": 2, "visibility": 14.11, "ozone": 289.95 }, { */ $newJSON = array(); // storage for the merry-timeline JSON /* { "color": "#b7b2db", "text": "Flurries", "annotation": "0°", "time": 1672257600 }, */ $tempUOM = str_replace('°'," ",$UnitsTab[$showUnitsAs]['T']); foreach($JSON['hourly']['data'] as $i => $H) { $dayname = date('l',$H['time']); if(isset($tranTab[$dayname])) {$dayname = $tranTab[$dayname]; if($doIconv) {iconv($charsetInput,$charsetOutput.'//TRANSLIT',$dayname); } $dayname .= ', '.date('d',$H['time']); $tColor = isset($timelineColors[$H['summary']])?$timelineColors[$H['summary']]:'#fefefe'; $text = isset($tranTab[$H['summary']])?$tranTab[$H['summary']]:$H['summary']; if($doIconv) {iconv($charsetInput,$charsetOutput.'//TRANSLIT',$text);} $newJSON[$dayname][] = array( 'color' => $tColor, 'text' => $text, 'annotation' => round($H['temperature'],0).$tempUOM, 'time' => $H['time'] ); } // end each hourly forecast parsing } // end process hourly forecast data $utfdata = json_encode($newJSON,JSON_UNESCAPED_UNICODE); $merrytimelineJSON = ($doIconv)?iconv('UTF-8',$charsetOutput.'//TRANSLIT//IGNORE',$utfdata):$utfdata; $hourlyData = "\n"; if(isset($_GET['debug'])) { $hourlyData .= "\n"; } if(isset($_GET['snapshot'])) { file_put_contents('./raw-weatherData-json.txt',$merrytimelineJSON); file_put_contents('./raw-newJSON-array.txt',var_export($newJSON,true)); $Status .= "\n"; } /* old version if(isset($JSON['hourly']['data'][0]['time'])) { // process Hourly forecast data /* "hourly": { "summary": "Mostly cloudy throughout the day.", "icon": "partly-cloudy-night", "data": [{ "time": 1548018000, "summary": "Mostly Cloudy", "icon": "partly-cloudy-day", "precipIntensity": 0.1422, "precipProbability": 0.29, "precipType": "rain", "temperature": 14.91, "apparentTemperature": 14.91, "dewPoint": 11.49, "humidity": 0.8, "pressure": 1017.89, "windSpeed": 10.8, "windGust": 24.54, "windBearing": 226, "cloudCover": 0.88, "uvIndex": 2, "visibility": 14.11, "ozone": 289.95 }, { // foreach($JSON['hourly']['data'] as $i => $FCpart) { $PWforecasticonHR[$i] = PW_gen_hourforecast($FCpart); if($doIconv) { $PWforecasticonHR[$i]['icon'] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWforecasticonHR[$i]['icon']). ' '; $PWforecasticonHR[$i]['temp'] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWforecasticonHR[$i]['temp']). ' '; $PWforecasticonHR[$i]['wind'] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWforecasticonHR[$i]['wind']). ' '; $PWforecasticonHR[$i]['precip'] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$PWforecasticonHR[$i]['precip']). ' '; } if($doDebug) { $Status .= "\n"; } } // end each hourly forecast parsing */ } // end process hourly forecast data } // end got good JSON decode/process // end process JSON style -------------------------------------------------------------------- // All finished with parsing, now prepare to print $wdth = intval(100/count($PWforecasticons)); $ndays = intval(count($PWforecasticon)/2); $doNumIcons = $maxIcons; if(count($PWforecasticons) < $maxIcons) { $doNumIcons = count($PWforecasticons); } $IncludeMode = false; $PrintMode = true; if (isset($doPrintPW) && ! $doPrintPW ) { print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'noprint' ) { print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'y') { $IncludeMode = true; } if (isset($doIncludePW)) { $IncludeMode = $doIncludePW; } $printHeading = true; $printIcons = true; $printText = true; if (isset($doPrintHeadingPW)) { $printHeading = $doPrintHeadingPW; } if (isset($_REQUEST['heading']) ) { $printHeading = substr(strtolower($_REQUEST['heading']),0,1) == 'y'; } if (isset($doPrintIconsPW)) { $printIcons = $doPrintIconsPW; } if (isset($_REQUEST['icons']) ) { $printIcons = substr(strtolower($_REQUEST['icons']),0,1) == 'y'; } if (isset($doPrintTextPW)) { $printText = $doPrintTextPW; } if (isset($_REQUEST['text']) ) { $printText = substr(strtolower($_REQUEST['text']),0,1) == 'y'; } if (! $IncludeMode and $PrintMode) { ?> <?php echo $PWtitle . ' - ' . $PWforecastcity; ?> Sorry.. this forecast can not be processed at this time. EONAG ; } if (strlen($PWforecasttext[0])<2 and $PrintMode and ! $UnSupported ) { echo '

'.langtransstr('Forecast blank?').' ' . langtransstr('Force Update').'

'; } if ($PrintMode and ($printHeading or $printIcons)) { ?> \n"; } ?>
\n"; print $PWcurrentConditions; print "
0) { echo "
$PWupdated\n"; } ?>

 

\n"; $maxChars = 135; if($iTitleLen >= $maxChars or $iCondLen >= $maxChars or $iTempLen >= $maxChars ) { print "\n"; $doFoldRow = true; } } $startIcon = 0; $finIcon = $doNumIcons; $incr = $doNumIcons; $doFoldRow = false; if ($doFoldRow) { $wdth = $wdth*2; $incr = $numIconsInFoldedRow; } print "\n"; for ($k=$startIcon;$k<$doNumIcons-1;$k+=$incr) { // loop over icon rows, 5 at a time until done $startIcon = $k; if ($doFoldRow) { $finIcon = $startIcon+$numIconsInFoldedRow; } else { $finIcon = $doNumIcons; } $finIcon = min($finIcon,$doNumIcons); print "\n"; print " \n"; for ($i=$startIcon;$i<$finIcon;$i++) { $ni = $doRTL?$numIconsInFoldedRow-1-$i+$startIcon+$k:$i; print "\n"; print "\n"; } print " \n"; print " \n"; for ($i=$startIcon;$i<$finIcon;$i++) { $ni = $doRTL?$numIconsInFoldedRow-1-$i+$startIcon+$k:$i; print "\n"; } ?> $PWforecastcond[$ni]\n"; } print " \n"; print " \n"; for ($i=$startIcon;$i<$finIcon;$i++) { $ni = $doRTL?$numIconsInFoldedRow-1-$i+$startIcon+$k:$i; print "\n"; } ?> \n"; for ($i=$startIcon;$i<$finIcon;$i++) { $ni = $doRTL?$numIconsInFoldedRow-1-$i+$startIcon+$k:$i; print "\n"; } ?> \n"; for ($i=$startIcon;$i<$finIcon;$i++) { print "\n"; } print "\n"; } // end doFoldRow ?>
$PWforecasttitles[$ni]
" . PW_img_replace($PWforecasticon[$ni],$PWforecastcond[$ni],$PWforecastpop[$ni],$PWforecastcloudcover[$ni]) . "
$PWforecasttemp[$ni]
"; if($PWforecastpop[$ni] > 0) { print "PoP: $PWforecastpop[$ni]%"; } else { print " "; } print "
 

'') { if($doIconv) { $PWforecastwarnings = iconv($charsetInput,$charsetOutput.'//IGNORE',$PWforecastwarnings); } $tW = 'width: 640px;'; if($doRTL) {$tW .= 'direction: rtl;';} print "

$PWforecastwarnings

\n"; } ?>
\n"; if(!$doRTL) { // normal Left-to-right print "\n"; print "\n"; } else { // print RTL format print "\n"; print "\n"; } print "\n"; } ?>
$PWforecasttitles[$i]
 
$PWforecasttext[$i]$PWforecasttext[$i]$PWforecasttitles[$i]
 

\n"; for ($n=$row*8;$n<$row*8+8;$n++) { $ni = $doRTL?($row+1)*8-$n-1+($row*8):$n; if(isset($PWforecasticonHR[$ni]['icon'])) { print ''.$PWforecasticonHR[$ni]['icon']."";; } else { print " "; } } print "\n"; print " \n"; for ($n=$row*8;$n<$row*8+8;$n++) { $ni = $doRTL?($row+1)*8-$n-1+($row*8):$n; if(isset($PWforecasticonHR[$ni]['temp'])) { print ''.$PWforecasticonHR[$ni]['temp']."";; } else { print " "; } } print "\n"; print " \n"; for ($n=$row*8;$n<$row*8+8;$n++) { $ni = $doRTL?($row+1)*8-$n-1+($row*8):$n; if(isset($PWforecasticonHR[$ni]['UV'])) { print ''.$PWforecasticonHR[$ni]['UV']."";; } else { print " "; } } print "\n"; print " \n"; for ($n=$row*8;$n<$row*8+8;$n++) { $ni = $doRTL?($row+1)*8-$n-1+($row*8):$n; if(isset($PWforecasticonHR[$ni]['wind'])) { print ''.$PWforecasticonHR[$ni]['wind']."";; } else { print " "; } } print "\n"; print " \n"; for ($n=$row*8;$n<$row*8+8;$n++) { $ni = $doRTL?($row+1)*8-$n-1+($row*8):$n; if(isset($PWforecasticonHR[$ni]['precip'])) { print ''.$PWforecasticonHR[$ni]['precip']."";; } else { print " "; } } print "\n"; print "
\n"; } // end rows */ ?>

Timeline display based on Merry-Timeline by Guillaume Carbonneau

 

PirateWeather.net. ".langtransstr('Animated forecast icons courtesy of')." www.meteotreviglio.com."; } if(strlen($dsSources) > 1) { print "
".langtransstr('Sources for this forecast').": $dsSources\n"; } print "

\n"; ?> \n"; $ch = curl_init(); // initialize a cURL session curl_setopt($ch, CURLOPT_URL, $theURL); // connect to provided URL curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // don't verify peer certificate curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (PW-forecast.php - saratoga-weather.org)'); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $numberOfSeconds); // connection timeout curl_setopt($ch, CURLOPT_TIMEOUT, $numberOfSeconds); // data timeout curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // return the data transfer curl_setopt($ch, CURLOPT_NOBODY, false); // set nobody curl_setopt($ch, CURLOPT_HEADER, true); // include header information if (isset($needCookie[$domain])) { curl_setopt($ch, $needCookie[$domain]); // set the cookie for this request curl_setopt($ch, CURLOPT_COOKIESESSION, true); // and ignore prior cookies $Status .= "\n"; } $data = curl_exec($ch); // execute session if(curl_error($ch) <> '') { // IF there is an error $Status .= "\n"; // display error notice } $cinfo = curl_getinfo($ch); // get info on curl exec. /* curl info sample Array ( [url] => http://saratoga-weather.net/clientraw.txt [content_type] => text/plain [http_code] => 200 [header_size] => 266 [request_size] => 141 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.125 [namelookup_time] => 0.016 [connect_time] => 0.063 [pretransfer_time] => 0.063 [size_upload] => 0 [size_download] => 758 [speed_download] => 6064 [speed_upload] => 0 [download_content_length] => 758 [upload_content_length] => -1 [starttransfer_time] => 0.125 [redirect_time] => 0 [redirect_url] => [primary_ip] => 74.208.149.102 [certinfo] => Array ( ) [primary_port] => 80 [local_ip] => 192.168.1.104 [local_port] => 54156 ) */ $Status .= "\n"; //$Status .= "\n"; curl_close($ch); // close the cURL session //$Status .= "\n"; $i = strpos($data,"\r\n\r\n"); $headers = substr($data,0,$i); $content = substr($data,$i+4); if($cinfo['http_code'] <> 200) { $Status .= "\n"; } return $data; // return headers+contents } else { // print "\n"; $STRopts = array( 'http'=>array( 'method'=>"GET", 'protocol_version' => 1.1, 'header'=>"Cache-Control: no-cache, must-revalidate\r\n" . "Cache-control: max-age=0\r\n" . "Connection: close\r\n" . "User-agent: Mozilla/5.0 (PW-forecast.php - saratoga-weather.org)\r\n" . "Accept: text/plain,text/html\r\n" ), 'https'=>array( 'method'=>"GET", 'protocol_version' => 1.1, 'header'=>"Cache-Control: no-cache, must-revalidate\r\n" . "Cache-control: max-age=0\r\n" . "Connection: close\r\n" . "User-agent: Mozilla/5.0 (PW-forecast.php - saratoga-weather.org)\r\n" . "Accept: text/plain,text/html\r\n" ) ); $STRcontext = stream_context_create($STRopts); $T_start = PW_fetch_microtime(); $xml = file_get_contents($url,false,$STRcontext); $T_close = PW_fetch_microtime(); $headerarray = get_headers($url,0); $theaders = join("\r\n",$headerarray); $xml = $theaders . "\r\n\r\n" . $xml; $ms_total = sprintf("%01.3f",round($T_close - $T_start,3)); $Status .= "\n"; $Status .= "<-- get_headers returns\n".$theaders."\n -->\n"; // print " file() stats: total=$ms_total secs.\n"; $overall_end = time(); $overall_elapsed = $overall_end - $overall_start; $Status .= "\n"; // print "fetch function elapsed= $overall_elapsed secs.\n"; return($xml); } } // end PW_fetch_URL // ------------------------------------------------------------------ function PW_fetch_microtime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } // ------------------------------------------------------------------------------------------- function PW_img_replace ( $PWimage, $PWcondtext,$PWpop,$PWcloudcover) { // // optionally replace the WeatherUnderground icon with an NWS icon instead. // global $NWSiconlist,$iconDir,$iconType,$Status; $curicon = isset($NWSiconlist[$PWimage])?$NWSiconlist[$PWimage]:''; // translated icon (if any) $tCCicon = PW_octets($PWcloudcover); if (!$curicon) { // no change.. use PW icon return("\"$PWcondtext\""); } // override icon with cloud coverage octets for Images of partly-cloudy-* and clear-* if(preg_match('/^(partly|clear)/i',$PWimage)) { $curicon = $tCCicon.'.jpg'; if(strpos($PWimage,'-night') !==false) { $curicon = 'n'.$curicon; } $Status .= "\n"; } if(preg_match('/^wind/i',$PWimage) and $iconType !== '.gif') { // note: Meteotriviglio icons do not have the wind_{sky}.gif icons, only wind.gif $curicon = 'wind_'.$tCCicon.'.jpg'; if(strpos($PWimage,'-night') !==false) { $curicon = 'n'.$curicon; } $Status .= "\n"; } if($iconType <> '.jpg') { $curicon = preg_replace('|\.jpg|',$iconType,$curicon); } $Status .= "\n"; return("\"$PWcondtext\""); } // ------------------------------------------------------------------------------------------- function PW_prepareJSON($input) { global $Status; //This will convert ASCII/ISO-8859-1 to UTF-8. //Be careful with the third parameter (encoding detect list), because //if set wrong, some input encodings will get garbled (including UTF-8!) list($isUTF8,$offset,$msg) = PW_check_utf8($input); if(!$isUTF8) { $Status .= "\n"; $str = utf8_encode($input); list($isUTF8,$offset,$msg) = PW_check_utf8($str); $Status .= "\n"; } else { $Status .= "\n"; $str = $input; } //Remove UTF-8 BOM if present, json_decode() does not like it. if(substr($str, 0, 3) == pack("CCC", 0xEF, 0xBB, 0xBF)) $str = substr($str, 3); return $str; } // ------------------------------------------------------------------------------------------- function PW_check_utf8($str) { // check all the characters for UTF-8 compliance so json_decode() won't choke // Sometimes, an ISO international character slips in the PW text string. $len = strlen($str); for($i = 0; $i < $len; $i++){ $c = ord($str[$i]); if ($c > 128) { if (($c > 247)) return array(false,$i,"c>247 c='$c'"); elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($c > 191) $bytes = 2; else return false; if (($i + $bytes) > $len) return array(false,$i,"i+bytes>len bytes=$bytes,len=$len"); while ($bytes > 1) { $i++; $b = ord($str[$i]); if ($b < 128 || $b > 191) return array(false,$i,"128191 b=$b"); $bytes--; } } } return array(true,$i,"Success. Valid UTF-8"); } // end of check_utf8 // ------------------------------------------------------------------------------------------- function PW_decode_JSON_error() { $Status = ''; $Status .= "\n"; return($Status); } // ------------------------------------------------------------------------------------------- function PW_fixup_text($text) { global $Status; // attempt to convert Imperial forecast temperatures to Metric in the text forecast if(preg_match_all('!([-|\d]+)([ º]*F)!s',$text,$m)) { //$newtext = str_replace('ºF','F',$text); $newtext = $text; foreach ($m[1] as $i => $tF) { $tI = $m[2][$i]; $tC = (float)(($tF - 32) / 1.8 ); $tC = round($tC,0); // $newtext = str_replace("{$tF}F","{$tC}C({$tF}F)",$newtext); $newtext = str_replace("{$tF}{$tI}","{$tC}C",$newtext); $Status .= "\n"; } return($newtext); } else { return($text); // no changes } } function PW_loadLangDefaults () { global $PWlanguages, $PWlangCharsets; /* en - [DEFAULT] English ar - Arabic az - Azerbaijani be - Belarusian bg - Bulgarian bs - Bosnian ca - Catalan cz - Czech da - Danish de - German fi - Finnish fr - French el - Greek et - Estonian hr - Croation hu - Hungarian id - Indonesian it - Italian is - Icelandic kw - Cornish lt - Lithuanian nb - Norwegian Bokmål nl - Dutch pl - Polish pt - Portuguese ro - Romanian ru - Russian sk - Slovak sl - Slovenian sr - Serbian sv - Swedish tr - Turkish uk - Ukrainian */ $PWlanguages = array( // our template language codes v.s. lang:LL codes for JSON 'af' => 'en', 'bg' => 'bg', 'cs' => 'cs', 'ct' => 'ca', 'dk' => 'da', 'nl' => 'nl', 'en' => 'en', 'fi' => 'fi', 'fr' => 'fr', 'de' => 'de', 'el' => 'el', 'ga' => 'en', 'it' => 'it', 'he' => 'he', 'hu' => 'hu', 'no' => 'nb', 'pl' => 'pl', 'pt' => 'pt', 'ro' => 'ro', 'es' => 'es', 'se' => 'sv', 'si' => 'sl', 'sk' => 'sk', 'sr' => 'sr', ); $PWlangCharsets = array( 'bg' => 'ISO-8859-5', 'cs' => 'ISO-8859-2', 'el' => 'ISO-8859-7', 'he' => 'UTF-8', 'hu' => 'ISO-8859-2', 'ro' => 'ISO-8859-2', 'pl' => 'ISO-8859-2', 'si' => 'ISO-8859-2', 'sk' => 'Windows-1250', 'sr' => 'Windows-1250', 'ru' => 'ISO-8859-5', ); } // end loadLangDefaults function PW_loadTranslate ($lang,$charsetOutput) { global $Status; /* Note: We packed up the translation array as it is a mix of various character set types and editing the raw text can easily change the character presentation. The TRANTABLE was created by using $transSerial = serialize($transArray); $b64 = base64_encode($transSerial); print "\n"; $tArr = str_split($b64,72); print "define('TRANTABLE',\n'"; $tStr = ''; foreach($tArr as $rec) { $tStr .= $rec."\n"; } $tStr = trim($tStr); print $tStr; print "'); // end of TRANTABLE encoded\n"; and that result included here. It will reconstitute with unserialize(base64_decode(TRANTABLE)) to look like: ... 'dk' => array ( 'charset' => 'ISO-8859-1', 'Sunday' => 'Søndag', 'Monday' => 'Mandag', 'Tuesday' => 'Tirsdag', 'Wednesday' => 'Onsdag', 'Thursday' => 'Torsdag', 'Friday' => 'Fredag', 'Saturday' => 'Lørdag', 'Sunday night' => 'Søndag nat', 'Monday night' => 'Mandag nat', 'Tuesday night' => 'Tirsdag nat', 'Wednesday night' => 'Onsdag nat', 'Thursday night' => 'Torsdag nat', 'Friday night' => 'Fredag nat', 'Saturday night' => 'Lørdag nat', 'Today' => 'I dag', 'Tonight' => 'I nat', 'This afternoon' => 'I eftermiddag', 'Rest of tonight' => 'Resten af natten', ), // end dk ... and the array for the chosen language will be returned, or the English version if the language is not in the array. */ if(!file_exists("PW-forecast-lang.php")) { print "

Warning: PW-forecast-lang.php translation file was not found. It is required"; print " to be in the same directory as PW-forecast.php.

\n"; exit; } include_once("PW-forecast-lang.php"); $default = array( 'charset' => 'ISO-8859-1', 'Sunday' => 'Sunday', 'Monday' => 'Monday', 'Tuesday' => 'Tuesday', 'Wednesday' => 'Wednesday', 'Thursday' => 'Thursday', 'Friday' => 'Friday', 'Saturday' => 'Saturday', 'Sunday night' => 'Sunday night', 'Monday night' => 'Monday night', 'Tuesday night' => 'Tuesday night', 'Wednesday night' => 'Wednesday night', 'Thursday night' => 'Thursday night', 'Friday night' => 'Friday night', 'Saturday night' => 'Saturday night', 'Today' => 'Today', 'Tonight' => 'Tonight', 'This afternoon' => 'This afternoon', 'Rest of tonight' => 'Rest of tonight', 'High:' => 'High:', 'Low:' => 'Low:', 'Updated:' => 'Updated:', 'Pirateweather Forecast for:' => 'Pirateweather Forecast for:', 'NESW' => 'NESW', // cardinal wind directions 'Wind' => 'Wind', 'UV index' => 'UV Index', 'Chance of precipitation' => 'Chance of precipitation', 'mph' => 'mph', 'kph' => 'km/h', 'mps' => 'm/s', 'Temperature' => 'Temperature', 'Barometer' => 'Barometer', 'Dew Point' => 'Dew Point', 'Humidity' => 'Humidity', 'Visibility' => 'Visibility', 'Wind chill' => 'Wind chill', 'Heat index' => 'Heat index', 'Humidex' => 'Humidex', 'Sunrise' => 'Sunrise', 'Sunset' => 'Sunset', 'Currently' => 'Currently', 'rain' => 'rain', 'snow' => 'snow', 'sleet' => 'sleet', 'Weather conditions at 999 from forecast point.' => 'Weather conditions at 999 from forecast point.', 'Daily Forecast' => 'Daily Forecast', 'Hourly Forecast' => 'Hourly Forecast', 'Meteogram' => 'Meteogram', ); $t = unserialize(base64_decode(TRANTABLE)); if(isset($t[$lang])) { $Status .= "\n"; $ourLang = $t[$lang]; /* if($charsetOutput !== 'UTF-8') { foreach ($ourLang as $term => $val) { $ourLang[$term] = iconv('UTF-8',$charsetOutput.'//IGNORE',$val); } $Status .= "\n"; } */ return($ourLang); } else { $Status .= "\n"; return($default); } } // ------------------------------------------------------------------ // convert degrees into wind direction abbreviation function PW_WindDir ($degrees) { // figure out a text value for compass direction // Given the wind direction, return the text label // for that value. 16 point compass $winddir = $degrees; if ($winddir == "n/a") { return($winddir); } if (!isset($winddir)) { return "---"; } if (!is_numeric($winddir)) { return($winddir); } $windlabel = array ("N","NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW","SW", "WSW", "W", "WNW", "NW", "NNW"); $dir = $windlabel[ (integer)fmod((($winddir + 11) / 22.5),16) ]; return($dir); } // end function PW_WindDir // ------------------------------------------------------------------ function PW_WindDirTrans($inwdir) { global $tranTab, $Status, $charsetOutput; $wdirs = $tranTab['NESW']; // default directions $tstr = $inwdir; $tStatus = "\n"; if($charsetOutput !== 'UTF-8') { $tStatus = iconv('UTF-8',$charsetOutput.'//TRANSLIT//IGNORE',$tStatus); } $Status .= $tStatus; return($tstr); } function PW_round($item,$dp) { $t = round($item,$dp); if ($t == '-0') { $t = 0; } return ($t); } function PW_sources ($sArray) { $lookupSources = array( 'cmc' => 'The USA NCEP’s Canadian Meteorological Center ensemble model|http://nomads.ncep.noaa.gov/txt_descriptions/CMCENS_doc.shtml', 'darksky' => 'Dark Sky’s own hyperlocal precipitation forecasting system, backed by radar data from the USA NOAA’s NEXRAD system, available in the USA, and the UK Met Office’s NIMROD system, available in the UK and Ireland.|https://darksky.net/', 'pirateweather' => 'PirateWeather’s own hyperlocal precipitation forecasting system, backed by radar data from the USA NOAA’s NEXRAD system, available in the USA, and the UK Met Office’s NIMROD system, available in the UK and Ireland.|https://pirateweather.net/', 'ecpa' => 'Environment and Climate Change Canada’s Public Alert system|https://weather.gc.ca/warnings/index_e.html', 'gfs' => 'The USA NOAA’s Global Forecast System|http://en.wikipedia.org/wiki/Global_Forecast_System', 'gefs' => 'The Global Ensemble Forecast System (GEFS) is the ensemble version of NOAA\'s GFS model|https://www.ncei.noaa.gov/products/weather-climate-models/global-ensemble-forecast', 'hrrr' => 'The USA NOAA’s High-Resolution Rapid Refresh Model|https://rapidrefresh.noaa.gov/hrrr/', 'hrrrsubh' => 'The USA NOAA’s High-Resolution Rapid Refresh Model sub-hour |https://rapidrefresh.noaa.gov/hrrr/', 'ETOPO1' => '1 Arc-Minute Global Relief Model from NCEI at USA NOAA |https://www.ncei.noaa.gov/products/etopo-global-relief-model', 'icon' => 'The German Meteorological Office’s icosahedral nonhydrostatic|https://www.dwd.de/EN/research/weatherforecasting/num_modelling/01_num_weather_prediction_modells/icon_description.html', 'isd' => 'The USA NOAA’s Integrated Surface Database|https://www.ncdc.noaa.gov/isd', 'madis' => 'The USA NOAA/ESRL’s Meteorological Assimilation Data Ingest System|https://madis.noaa.gov/', 'meteoalarm' => 'EUMETNET’s Meteoalarm weather alerting system|https://meteoalarm.eu/', 'nam' => 'The USA NOAA’s North American Mesoscale Model|http://en.wikipedia.org/wiki/North_American_Mesoscale_Model', 'nwspa' => 'The USA NOAA’s Public Alert system|https://alerts.weather.gov/', 'sref' => 'The USA NOAA/NCEP’s Short-Range Ensemble Forecast|https://www.emc.ncep.noaa.gov/mmb/SREF/SREF.html', 'era5' => 'European Reanalysis 5 Dataset is used to provide historic weather data.|https://registry.opendata.aws/ecmwf-era5/', ); $outStr = ''; foreach ($sArray as $source) { if(isset($lookupSources[$source])) { list($title,$url) = explode('|',$lookupSources[$source]); if(strlen($outStr) > 1) {$outStr .= ', ';} $outStr .= "".strtoupper($source)."\n"; } } return ($outStr); } function PW_octets ($coverage) { global $Status; $octets = round($coverage*100 / 12.5,1); $Status .= "\n"; return('skc'); } elseif ($octets < 3.0) { $Status .= " clouds=few -->\n"; return('few'); } elseif ($octets < 5.0) { $Status .= " clouds=sct -->\n"; return('sct'); } elseif ($octets < 8.0) { $Status .= " clouds=bkn -->\n"; return('bkn'); } else { $Status .= " clouds=ovc -->\n"; return('ovc'); } } function PW_conv_baro($hPa) { # even 'us' imperial returns pressure in hPa so we need to convert global $showUnitsAs; if($showUnitsAs == 'us') { $t = (float)$hPa * 0.02952998751; return(sprintf("%01.2f",$t)); } else { return( sprintf("%01.1f",$hPa) ); } } function PW_gen_hourforecast($FCpart) { global $doDebug,$Status,$showTempsAs,$tranTab,$windUnit,$Units,$showUnitsAs; /* $FCpart = { "time": 1548018000, "summary": "Mostly Cloudy", "icon": "partly-cloudy-day", "precipIntensity": 0.1422, "precipProbability": 0.29, "precipType": "rain", "temperature": 14.91, "apparentTemperature": 14.91, "dewPoint": 11.49, "humidity": 0.8, "pressure": 1017.89, "windSpeed": 10.8, "windGust": 24.54, "windBearing": 226, "cloudCover": 0.88, "uvIndex": 2, "visibility": 14.11, "ozone": 289.95 } */ $PWH = array(); //$newIcon = ''; if($showUnitsAs == 'us') { $t = explode(' ',date('g:ia n/j l',$FCpart['time'])); } else { $t = explode(' ',date('H:i j/n l',$FCpart['time'])); } $newIcon = ''.$t[0].'
'.$tranTab[$t[2]]."

\n"; $cloudcover = $FCpart['cloudCover']; if(isset($FCpart['precipProbability'])) { $pop = round($FCpart['precipProbability'],1)*100; } else { $pop = 0; } $temp = explode('.',$FCpart['summary'].'.'); // split as sentences (sort of). $condition = trim($temp[0]); // take first one as summary. $condition = isset($tranTab[$condition])?$tranTab[$condition]:$condition; $icon = $FCpart['icon']; $newIcon .= "
" . PW_img_replace( $icon,$condition,$pop,$cloudcover) . "
" . $condition; $PWH['icon'] = $newIcon; $PWH['temp'] = ''.PW_round($FCpart['temperature'],0)."°$showTempsAs"; $PWH['UV'] = 'UV: '.$FCpart['uvIndex'].""; $tWdir = PW_WindDir(round($FCpart['windBearing'],0)); $PWH['wind'] = $tranTab['Wind']." ".PW_WindDirTrans($tWdir); $PWH['wind'] .= " ". round($FCpart['windSpeed'],0)."->".round($FCpart['windGust'],0) . " $windUnit\n"; if(isset($FCpart['precipType'])) { $preciptype = $FCpart['precipType']; } else { $preciptype = ''; } $tstr = ''; if($pop > 0) { if(!empty($preciptype)) { $t = explode(',',$preciptype.','); foreach ($t as $k => $ptype) { if(!empty($ptype)) {$tstr .= $tranTab[$ptype].',';} } if(isset($FCpart['precipAccumulation'])) { $amt = $FCpart['precipAccumulation']; if($showUnitsAs == 'us') { $U = 'in'; } else { $U = 'cm'; } $accum = ' ' . sprintf("%01.2f",$amt)."$U"; } else { $accum = ''; } if(strlen($tstr)>0) { $tstr = substr($tstr,0,strlen($tstr)-1). $accum; } else { $tstr = ' '; } } } $PWH['precip'] = "$tstr"; //$newIcon .= "\n"; return($PWH); } function setup_tabber() { ?> $data) { $output .= "{\"$day\":["; foreach ($data as $i => $vals) { $output .= " } */ // End of functions --------------------------------------------------------------------------