/[drupal]/contributions/modules/weather/weather_parser.inc
ViewVC logotype

Contents of /contributions/modules/weather/weather_parser.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.23 - (show annotations) (download) (as text)
Mon Sep 28 13:14:28 2009 UTC (8 weeks, 3 days ago) by toddy
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +1 -1 lines
File MIME type: text/x-php
Merge changes from DRUPAL-6--5-6 to DRUPAL-6--5-7
1 <?php
2 /* $Id: weather_parser.inc,v 1.21.2.7 2009/09/28 12:05:48 toddy Exp $
3 *
4 * Copyright © 2006-2009 Tobias Quathamer <t.quathamer@gmx.net>
5 *
6 * This file is part of the Drupal Weather module.
7 *
8 * Weather is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * Weather is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Weather; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23
24
25 /**
26 * Parses a raw METAR data string
27 */
28 function weather_parse_metar($metar_raw_string) {
29 // Some stations insert a space between the cloud conditions
30 // and the altitude, e.g. "FEW 025" instead of "FEW025".
31 // Therefore, we scan for such occurences and remove the space.
32 $metar_raw_string = preg_replace("/(FEW|SCT|BKN|OVC)\s+([0-9]{3})/",
33 '$1$2', $metar_raw_string);
34
35 // Setup the metar data array
36 $metar = array();
37 $metar['#raw'] = $metar_raw_string;
38 // Split string for parsing routines
39 $raw_items = preg_split('/\s+/', strtoupper($metar_raw_string));
40
41 // Run the data through the METAR routines
42 foreach ($raw_items as $metar_raw) {
43 if (_weather_parse_stop($metar_raw, $metar)) break;
44 _weather_parse_icao($metar_raw, $metar);
45 _weather_parse_timestamp($metar_raw, $metar);
46 _weather_parse_reporttype($metar_raw, $metar);
47 _weather_parse_wind($metar_raw, $metar);
48 _weather_parse_visibility($metar_raw, $metar);
49 _weather_parse_condition($metar_raw, $metar);
50 _weather_parse_phenomena($metar_raw, $metar);
51 _weather_parse_temperature($metar_raw, $metar);
52 _weather_parse_pressure($metar_raw, $metar);
53 }
54
55 // Calculate sunrise and sunset times
56 _weather_calculate_sunrise_sunset($metar);
57
58 return $metar;
59 }
60
61
62
63
64 /**
65 * Decide whether to stop parsing
66 *
67 * @param string Raw METAR data to parse
68 * @param array Parsed METAR data, will be altered
69 * @return boolean
70 */
71 function _weather_parse_stop($metar_raw, &$metar) {
72 if (preg_match('/^(BECMG|TEMPO|NOSIG|RMK)$/', $metar_raw)) {
73 return TRUE;
74 }
75 else {
76 return FALSE;
77 }
78 }
79
80
81
82 /**
83 * Extract the ICAO code
84 *
85 * ICAO = International Civil Aviation Organization, this is a four
86 * letter airport code, e. g. EDDH
87 *
88 * @param string Raw METAR data to parse
89 * @param array Parsed METAR data, will be altered
90 */
91 function _weather_parse_icao($metar_raw, &$metar) {
92 if (preg_match('/^([A-Z]{4}|K[A-Z0-9]{3})$/', $metar_raw) and !isset($metar['icao'])) {
93 $metar['icao'] = $metar_raw;
94 }
95 }
96
97
98
99 /**
100 * Extract the timestamp
101 *
102 * @param string Raw METAR data to parse
103 * @param array Parsed METAR data, will be altered
104 */
105 function _weather_parse_timestamp($metar_raw, &$metar) {
106 if (preg_match('/^([0-9]{2})([0-9]{2})([0-9]{2})Z$/', $metar_raw, $matches)) {
107 $timestamp['year'] = gmdate('Y');
108 $timestamp['month'] = gmdate('n');
109 $timestamp['day'] = $matches[1];
110 $timestamp['hour'] = $matches[2];
111 $timestamp['minute'] = $matches[3];
112 // if the current day is lower than the one from the METAR data,
113 // it must be a day from last month
114 // Note: in case even the year wraps (month = 0 -> month = 12, year--),
115 // the gmmktime() function further down will take care of this.
116 if (gmdate('d') < $timestamp['day']) {
117 $timestamp['month']--;
118 }
119
120 $metar['reported_on'] = gmmktime($timestamp['hour'],
121 $timestamp['minute'],
122 0, // these are the seconds
123 $timestamp['month'],
124 $timestamp['day'],
125 $timestamp['year']);
126 }
127 }
128
129
130
131 /**
132 * Extract the report type
133 *
134 * This may be missing in the METAR data. If present, it should be
135 * either AUTO or COR.
136 *
137 * @param string Raw METAR data to parse
138 * @param array Parsed METAR data, will be altered
139 */
140 function _weather_parse_reporttype($metar_raw, &$metar) {
141 if (preg_match('/^(AUTO|COR)$/', $metar_raw)) {
142 $metar['reporttype'] = $metar_raw;
143 }
144 }
145
146
147
148 /**
149 * Extract the wind information
150 *
151 * @param string Raw METAR data to parse
152 * @param array Parsed METAR data, will be altered
153 */
154 function _weather_parse_wind($metar_raw, &$metar) {
155 if (preg_match('/^'.
156 '([0-9]{3}|VRB)'. // Wind direction from true north or VRB for variable
157 '([0-9]{2,3})'. // Wind speed, two or three numbers
158 '(G([0-9]{2,3}))?'. // Gusts, two or three digits (optional)
159 '(KT|MPS|KMH)'. // Measurement unit (knots, meter/s, or km/h)
160 '$/', $metar_raw, $matches)) {
161 $metar['wind']['direction'] = (int) $matches[1];
162 $wind_speed = (int) $matches[2];
163 $wind_gusts = (int) $matches[4];
164 $wind_unit = $matches[5];
165
166 // Do a conversion to other formats
167 switch ($wind_unit) {
168 case 'KT':
169 // Convert from knots to km/h, mph, and mps
170 // nautical mile = 1852 meters
171 // statue mile = 1609.344 meters
172 $metar['wind']['speed_knots'] = $wind_speed;
173 $metar['wind']['gusts_knots'] = $wind_gusts;
174 $metar['wind']['speed_kmh'] = round($wind_speed * 1.852, 1);
175 $metar['wind']['gusts_kmh'] = round($wind_gusts * 1.852, 1);
176 $metar['wind']['speed_mph'] = round($wind_speed * 1.151, 1);
177 $metar['wind']['gusts_mph'] = round($wind_gusts * 1.151, 1);
178 $metar['wind']['speed_mps'] = round($wind_speed * 0.514, 1);
179 $metar['wind']['gusts_mps'] = round($wind_gusts * 0.514, 1);
180 break;
181 case 'MPS':
182 // Convert from meter/s to knots, km/h and mph
183 // nautical mile = 1852 meters
184 // statue mile = 1609.344 meters
185 $metar['wind']['speed_knots'] = round($wind_speed * 1.944, 1);
186 $metar['wind']['gusts_knots'] = round($wind_gusts * 1.944, 1);
187 $metar['wind']['speed_kmh'] = round($wind_speed * 3.6, 1);
188 $metar['wind']['gusts_kmh'] = round($wind_gusts * 3.6, 1);
189 $metar['wind']['speed_mph'] = round($wind_speed * 2.237, 1);
190 $metar['wind']['gusts_mph'] = round($wind_gusts * 2.237, 1);
191 $metar['wind']['speed_mps'] = $wind_speed;
192 $metar['wind']['gusts_mps'] = $wind_gusts;
193 break;
194 case 'KMH':
195 // Convert from km/h to knots, mph, and mps
196 // nautical mile = 1852 meters
197 // statue mile = 1609.344 meters
198 $metar['wind']['speed_knots'] = round($wind_speed * 0.540, 1);
199 $metar['wind']['gusts_knots'] = round($wind_gusts * 0.540, 1);
200 $metar['wind']['speed_kmh'] = $wind_speed;
201 $metar['wind']['gusts_kmh'] = $wind_gusts;
202 $metar['wind']['speed_mph'] = round($wind_speed * 0.621, 1);
203 $metar['wind']['gusts_mph'] = round($wind_gusts * 0.621, 1);
204 $metar['wind']['speed_mps'] = round($wind_speed * 0.278, 1);
205 $metar['wind']['gusts_mps'] = round($wind_gusts * 0.278, 1);
206 break;
207 }
208 $metar['wind']['speed_beaufort'] = _weather_calculate_beaufort($metar['wind']['speed_kmh']);
209 $metar['wind']['gusts_beaufort'] = _weather_calculate_beaufort($metar['wind']['gusts_kmh']);
210 }
211 else if (preg_match('/^'.
212 '([0-9]{3})'. // Variable wind direction, start
213 'V'. // Marker for "V"ariable
214 '([0-9]{3})'. // Variable wind direction, end
215 '$/', $metar_raw, $matches)) {
216 $metar['wind']['variable_start'] = (int) $matches[1];
217 $metar['wind']['variable_end'] = (int) $matches[2];
218 }
219 }
220
221
222
223 /**
224 * Extract the visibility information
225 *
226 * @param string Raw METAR data to parse
227 * @param array Parsed METAR data, will be altered
228 */
229 function _weather_parse_visibility($metar_raw, &$metar) {
230 if (preg_match('/^([0-9])$/', $metar_raw, $matches)) {
231 // Special case: A single digit, e.g. in 1 1/2SM
232 $metar['visibility']['#visibility_miles'] = $matches[1];
233 }
234 else if (preg_match('/^'.
235 '(M?)([0-9])(\/?)([0-9]*)'.
236 'SM'.
237 '$/', $metar_raw, $matches)) {
238 if ($matches[3] == '/') {
239 // This is a fractional visibility, we need to convert this
240 $visibility = $metar['visibility']['#visibility_miles'] + $matches[2] / $matches[4];
241 }
242 else {
243 $visibility = $matches[2] . $matches[4];
244 }
245 $metar['visibility']['miles'] = $visibility;
246 $metar['visibility']['kilometers'] = round($visibility * 1.609344, 1);
247 }
248 else if (preg_match('/^([0-9]{4})(NDV)?$/', $metar_raw, $matches)) {
249 // NDV means "no directional variation", used by automatic stations
250 $metar['visibility']['kilometers'] = round($matches[1] / 1000, 1);
251 $metar['visibility']['miles'] = round($metar['visibility']['kilometers'] / 1.609344, 1);
252 }
253 }
254
255
256
257 /**
258 * Extract the phenomena information
259 *
260 * @param string Raw METAR data to parse
261 * @param array Parsed METAR data, will be altered
262 */
263 function _weather_parse_phenomena($metar_raw, &$metar) {
264 if (preg_match('/^'.
265 '(-|\+|VC)?'. // Intensity or Proximity
266 '(SH|TS|FZ)?'. // Descriptor
267 'RA'. // Rain
268 '$/', $metar_raw, $matches)) {
269 $phen = array();
270 if (isset($matches[1])) {
271 switch ($matches[1]) {
272 case '-': $phen['#light'] = TRUE; break;
273 case '+': $phen['#heavy'] = TRUE; break;
274 default: $phen['#moderate'] = TRUE;
275 }
276 }
277 if (isset($matches[2])) {
278 switch ($matches[2]) {
279 case 'SH': $phen['#showers'] = TRUE; break;
280 case 'FZ': $phen['#freezing'] = TRUE; break;
281 }
282 }
283 $metar['phenomena']['rain'] = $phen;
284 }
285 else if (preg_match('/^'.
286 '(-|\+|VC)?'. // Intensity or Proximity
287 '(FZ)?'. // Descriptor
288 'DZ'. // Drizzle
289 '$/', $metar_raw, $matches)) {
290 $phen = array();
291 if (isset($matches[1])) {
292 switch ($matches[1]) {
293 case '-': $phen['#light'] = TRUE; break;
294 case '+': $phen['#heavy'] = TRUE; break;
295 default: $phen['#moderate'] = TRUE;
296 }
297 }
298 if (isset($matches[2])) {
299 switch ($matches[2]) {
300 case 'FZ': $phen['#freezing'] = TRUE; break;
301 }
302 }
303 $metar['phenomena']['drizzle'] = $phen;
304 }
305 else if (preg_match('/^'.
306 '(-|\+|VC)?'. // Intensity or Proximity
307 '(BL|DR)?'. // Descriptor
308 'SN'. // Snow
309 '$/', $metar_raw, $matches)) {
310 $phen = array();
311 if (isset($matches[1])) {
312 switch ($matches[1]) {
313 case '-': $phen['#light'] = TRUE; break;
314 case '+': $phen['#heavy'] = TRUE; break;
315 default: $phen['#moderate'] = TRUE;
316 }
317 }
318 if (isset($matches[2])) {
319 switch ($matches[2]) {
320 case 'BL': $phen['#blowing'] = TRUE; break;
321 case 'DR': $phen['#low_drifting'] = TRUE; break;
322 }
323 }
324 $metar['phenomena']['snow'] = $phen;
325 }
326 else if (preg_match('/^'.
327 'BR'. // Mist
328 '$/', $metar_raw, $matches)) {
329 $metar['phenomena']['#mist'] = TRUE;
330 }
331 else if (preg_match('/^'.
332 '(VC|MI|PR|BC)?'. // Proximity (VC) or Descriptor
333 'FG'. // Fog
334 '$/', $metar_raw, $matches)) {
335 $phen = array();
336 if (isset($matches[1])) {
337 switch ($matches[1]) {
338 case 'MI': $phen['#shallow'] = TRUE; break;
339 case 'PR': $phen['#partial'] = TRUE; break;
340 case 'BC': $phen['#patches'] = TRUE; break;
341 }
342 }
343 $metar['phenomena']['fog'] = $phen;
344 }
345 else if (preg_match('/^'.
346 'FU'. // Smoke
347 '$/', $metar_raw, $matches)) {
348 $metar['phenomena']['#smoke'] = TRUE;
349 }
350 }
351
352
353
354 /**
355 * Extract the condition information
356 *
357 * @param string Raw METAR data to parse
358 * @param array Parsed METAR data, will be altered
359 */
360 function _weather_parse_condition($metar_raw, &$metar) {
361 $ordering = array(
362 1 => array('CLR' => 'clear'),
363 2 => array('FEW' => 'few'),
364 3 => array('SCT' => 'scattered'),
365 4 => array('BKN' => 'broken'),
366 5 => array('OVC' => 'overcast')
367 );
368 $metar['condition_order'] = -1;
369 if (preg_match('/^'.
370 '(FEW|SCT|BKN|OVC)([0-9]{3})'.
371 '(CB|TCU)?(\/\/\/)?'.
372 '$/', $metar_raw, $matches)) {
373 foreach ($ordering as $order => $data) {
374 if (key($data) == $matches[1]) {
375 $metar['#condition_text'][] = $data[key($data)];
376 $metar['#condition_order'][] = $order;
377 break;
378 }
379 }
380 }
381 else if (preg_match('/^'.
382 '(CLR|SKC|CAVOK)'.
383 '$/', $metar_raw, $matches)) {
384 $metar['#condition_text'][] = 'clear';
385 $metar['#condition_order'][] = 1;
386 if ($matches[1] == 'CAVOK') {
387 $metar['visibility']['kilometers'] = 10;
388 $metar['visibility']['miles'] = round($metar['visibility']['kilometers'] / 1.609344, 1);
389 }
390 }
391 else if (preg_match('/^'.
392 '(NSC|NCD)'.
393 '$/', $metar_raw, $matches)) {
394 // NSC means no significant clouds,
395 // NCD is from automatic stations, no cloud detected
396 $metar['#condition_text'][] = 'no-significant-clouds';
397 $metar['#condition_order'][] = 1;
398 }
399 else if (preg_match('/^'.
400 'VV[0-9\/]{3}'.
401 '$/', $metar_raw, $matches)) {
402 // VV is the vertical visibility, this should be shown as overcast.
403 // If no information is available, VV/// will be used.
404 $metar['#condition_text'][] = 'overcast';
405 $metar['#condition_order'][] = 5;
406 }
407 if (isset($metar['#condition_order'])) {
408 foreach ($metar['#condition_order'] as $index => $order) {
409 if ($order > $metar['condition_order']) {
410 $metar['condition_order'] = $order;
411 $metar['condition_text'] = $metar['#condition_text'][$index];
412 }
413 }
414 }
415 }
416
417
418
419 /**
420 * Extract the temperature information
421 *
422 * @param string Raw METAR data to parse
423 * @param array Parsed METAR data, will be altered
424 */
425 function _weather_parse_temperature($metar_raw, &$metar) {
426 if (preg_match('/^'.
427 '(M?[0-9]{2})'. // Temperature (M indicates negative temperatures)
428 '\/'. // Slash is the separator
429 '(M?[0-9]{2}|XX)?'. // Optional: Dew point temperature, may be 'XX'
430 '$/', $metar_raw, $matches)) {
431 $metar['temperature']['celsius'] = (int) strtr($matches[1], 'M', '-');
432 $metar['temperature']['fahrenheit'] =
433 round($metar['temperature']['celsius'] * 9/5 + 32, 1);
434 if (isset($matches[2]) and $matches[2] != 'XX') {
435 $metar['dewpoint']['celsius'] = (int) strtr($matches[2], 'M', '-');
436 $metar['dewpoint']['fahrenheit'] =
437 round($metar['dewpoint']['celsius'] * 9/5 + 32, 1);
438 }
439 }
440 }
441
442
443
444 /**
445 * Extract the pressure information
446 *
447 * @param string Raw METAR data to parse
448 * @param array Parsed METAR data, will be altered
449 */
450 function _weather_parse_pressure($metar_raw, &$metar) {
451 if (preg_match('/^'.
452 '(A|Q)([0-9]{4})'. // Pressure, either inHg (A) or hPa (Q)
453 '$/', $metar_raw, $matches)) {
454 if ($matches[1] == 'A') {
455 // Pressure is given in inch Hg
456 $metar['pressure']['inHg'] = $matches[2] / 100;
457 $metar['pressure']['mmHg'] = round($metar['pressure']['inHg'] * 25.4, 0);
458 $metar['pressure']['hPa'] = round($metar['pressure']['inHg'] * 33.8639, 0);
459 $metar['pressure']['kPa'] = round($metar['pressure']['inHg'] * 3.38639, 1);
460 }
461 else {
462 // Pressure is given in HektoPascal, hPa
463 $metar['pressure']['hPa'] = (int) $matches[2];
464 $metar['pressure']['inHg'] = round($metar['pressure']['hPa'] * 0.02953, 2);
465 $metar['pressure']['mmHg'] = round($metar['pressure']['inHg'] * 25.4, 0);
466 $metar['pressure']['kPa'] = round($metar['pressure']['inHg'] * 3.38639, 1);
467 }
468 }
469 }
470
471
472
473 /**
474 * Calculate the times of sunrise and sunset
475 *
476 * The times are GMT, so it's possible for the sunrise being
477 * at 16:48 while the sun sets at 7:06.
478 *
479 * @param array Parsed METAR data, will be altered
480 */
481 function _weather_calculate_sunrise_sunset(&$metar) {
482 $info = weather_get_latitude_longitude($metar['icao']);
483
484 // reported_on is already GMT, so don't use gmdate()
485 $day_of_year = date('z', $metar['reported_on']);
486 $year = date('Y', $metar['reported_on']);
487 $month = date('m', $metar['reported_on']);
488 $day = date('d', $metar['reported_on']);
489
490 // setup pi constants: 0.5*pi, 1.0*pi, 1.5*pi, 2.0*pi
491 $pi_05 = 1.570796;
492 $pi_10 = 3.141593;
493 $pi_15 = 4.712389;
494 $pi_20 = 6.283185;
495
496 // convert latitude and longitude degree into radian
497 // x rad = y° * pi / 180 = 0.017453 * y°
498 $latitude = 0.017453 * $info['latitude'];
499 $longitude = 0.017453 * $info['longitude'];
500
501 // we want always GMT time, so set to 0. Otherwise,
502 // the timezone can be calculated as follows:
503 // $timezone = 0.261799 * offset;
504 $timezone = 0;
505
506 // the sunrise/sunset altitude in radian (-0.833°)
507 $altitude = -0.014539;
508
509 $sunrise = 0;
510 $sunset = 0;
511 foreach (array('sunrise' => $pi_05, 'sunset' => $pi_15) as $type => $factor) {
512 $a = $day_of_year + ($factor - $longitude) / $pi_20;
513 // solar mean anomaly
514 $sma = $a * 0.017202 - 0.0574039;
515 // solar true longitude
516 $stl = $sma + 0.0334405 * sin($sma);
517 $stl += 4.93289 + 3.49066E-04 * sin(2 * $sma);
518
519 // normalize the longitude to be between >= 0 and < 2.0*pi
520 while ($stl < 0) {
521 $stl += $pi_20;
522 }
523 while ($stl >= $pi_20) {
524 $stl -= $pi_20;
525 }
526
527 if ($stl / $pi_05 - intval($stl / $pi_05) == 0) {
528 $stl += 4.84814E-06;
529 }
530
531 // solar right ascension
532 $sra = sin($stl) / cos($stl);
533 $sra = atan2(0.91746 * $sra, 1);
534
535 // adjust quadrant
536 if ($stl > $pi_15) {
537 $sra += $pi_20;
538 }
539 else if ($stl > $pi_05) {
540 $sra += $pi_10;
541 }
542
543 // solar declination
544 $sd = 0.39782 * sin($stl);
545 $sd = $sd / sqrt(1 - $sd * $sd);
546 $sd = atan2($sd, 1);
547
548 $diurnal_arc = ($altitude - sin($sd) * sin($latitude)) / (cos($sd) * cos($latitude));
549
550 // is there a sunrise or sunset at all?
551 if ($diurnal_arc >= 1) {
552 // no sunrise
553 $no_sunrise = TRUE;
554 break;
555 }
556 if ($diurnal_arc <= -1) {
557 // no sunset
558 $no_sunset = TRUE;
559 break;
560 }
561
562 $diurnal_arc = $diurnal_arc / sqrt(1 - $diurnal_arc * $diurnal_arc);
563 $diurnal_arc = $pi_05 - atan2($diurnal_arc, 1);
564
565 if ($type == 'sunrise') {
566 $diurnal_arc = $pi_20 - $diurnal_arc;
567 }
568
569 // calculate the time
570 $localtime = $diurnal_arc + $sra - 0.0172028 * $a - 1.73364;
571 // wall clock time
572 $wallclock = $localtime - $longitude + $timezone;
573
574 // normalize wallclock to be between >= 0 and < 2.0*pi
575 while ($wallclock < 0) {
576 $wallclock += $pi_20;
577 }
578 while ($wallclock >= $pi_20) {
579 $wallclock -= $pi_20;
580 }
581 $wallclock = $wallclock * 3.81972;
582
583 $hour = intval($wallclock);
584 $minute = round(($wallclock - $hour) * 60, 0);
585
586 if ($type == 'sunrise') {
587 $sunrise = gmmktime($hour, $minute, 0, $month, $day, $year);
588 }
589 else {
590 $sunset = gmmktime($hour, $minute, 0, $month, $day, $year);
591 }
592 }
593
594 // handle special cases like no sunrise / sunset at all
595 if (isset($no_sunset)) {
596 $condition = 'day';
597 }
598 else if (isset($no_sunrise)) {
599 $condition = 'night';
600 }
601 else {
602 // correctly handle northern and southern hemisphere
603 if ($sunrise <= $sunset) {
604 // this should be on the northern hemisphere
605 if ($metar['reported_on'] >= $sunrise and $metar['reported_on'] < $sunset) {
606 $condition = 'day';
607 }
608 else {
609 $condition = 'night';
610 }
611 }
612 else {
613 // this should be on the southern hemisphere
614 if ($metar['reported_on'] >= $sunrise or $metar['reported_on'] <= $sunset) {
615 $condition = 'day';
616 }
617 else {
618 $condition = 'night';
619 }
620 }
621 }
622
623 $metar['daytime']['sunrise_on'] = $sunrise;
624 $metar['daytime']['sunset_on'] = $sunset;
625 if (isset($no_sunrise)) {
626 $metar['daytime']['no_sunrise'] = TRUE;
627 }
628 else {
629 $metar['daytime']['no_sunrise'] = FALSE;
630 }
631 if (isset($no_sunset)) {
632 $metar['daytime']['no_sunset'] = TRUE;
633 }
634 else {
635 $metar['daytime']['no_sunset'] = FALSE;
636 }
637 $metar['daytime']['condition'] = $condition;
638 }
639
640
641
642 /**
643 * Calculate Beaufort wind scale for given wind speed
644 *
645 * @link http://en.wikipedia.org/wiki/Beaufort_scale
646 *
647 * @param float Wind speed in km/h
648 * @return Beaufort number
649 */
650 function _weather_calculate_beaufort($wind_speed) {
651 if ($wind_speed >= 120) return 12;
652 if ($wind_speed >= 103) return 11;
653 if ($wind_speed >= 88) return 10;
654 if ($wind_speed >= 76) return 9;
655 if ($wind_speed >= 63) return 8;
656 if ($wind_speed >= 51) return 7;
657 if ($wind_speed >= 40) return 6;
658 if ($wind_speed >= 30) return 5;
659 if ($wind_speed >= 20) return 4;
660 if ($wind_speed >= 12) return 3;
661 if ($wind_speed >= 7) return 2;
662 if ($wind_speed >= 1) return 1;
663 return 0;
664 }

  ViewVC Help
Powered by ViewVC 1.1.2