public function parse($remaining_metar, $cavok = false)
 {
     $result = $this->consume($remaining_metar);
     $found = $result['found'];
     $new_remaining_metar = $result['remaining'];
     // handle the case where nothing has been found
     if ($found == null) {
         throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'Bad format for surface wind information', $this);
     }
     // handle the case where nothing is observed
     if ($found[1] == '///' && $found[2] == '//') {
         throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'No information measured for surface wind', $this);
     }
     // get unit used
     switch ($found[5]) {
         case 'KT':
             $speed_unit = Value::KNOT;
             break;
         case 'KPH':
             $speed_unit = Value::KILOMETER_PER_HOUR;
             break;
         case 'MPS':
             $speed_unit = Value::METER_PER_SECOND;
             break;
     }
     // retrieve and validate found params
     $surface_wind = new SurfaceWind();
     $surface_wind->setChunk(trim($found[0]));
     // mean speed
     $surface_wind->setMeanSpeed(Value::newIntValue($found[2], $speed_unit));
     // mean direction
     if ($found[1] == 'VRB') {
         $surface_wind->setVariableDirection(true);
         $surface_wind->setMeanDirection(null);
     } else {
         $mean_dir = Value::newIntValue($found[1], Value::DEGREE);
         if ($mean_dir->getValue() < 0 || $mean_dir->getValue() > 360) {
             throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'Wind direction should be in [0,360]', $this);
         }
         $surface_wind->setVariableDirection(false);
         $surface_wind->setMeanDirection($mean_dir);
     }
     // direction variations
     if (strlen($found[7]) > 0) {
         $min_dir_var = Value::newIntValue($found[7], Value::DEGREE);
         $max_dir_var = Value::newIntValue($found[8], Value::DEGREE);
         if ($min_dir_var->getValue() < 0 || $min_dir_var->getValue() > 360 || $max_dir_var->getValue() < 0 || $max_dir_var->getValue() > 360) {
             throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'Wind direction variations should be in [0,360]', $this);
         }
         $surface_wind->setDirectionVariations($min_dir_var, $max_dir_var);
     }
     // speed variations
     if (strlen($found[4]) > 0) {
         $surface_wind->setSpeedVariations(Value::newIntValue($found[4], $speed_unit));
     }
     // return result + remaining metar
     return array('result' => array('surfaceWind' => $surface_wind), 'remaining_metar' => $new_remaining_metar);
 }
 public function parse($remaining_metar, $cavok = false)
 {
     $result = $this->consume($remaining_metar);
     $found = $result['found'];
     $new_remaining_metar = $result['remaining'];
     // handle the case where nothing has been found
     if ($found == null) {
         throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'Bad format for visibility information', $this);
     }
     if ($found[1] == 'CAVOK') {
         // cloud and visibility OK
         $cavok = true;
         $visibility = null;
     } elseif ($found[1] == '////') {
         // information not available
         $cavok = false;
         $visibility = null;
     } else {
         $cavok = false;
         $visibility = new Visibility();
         if ($found[2] != null) {
             // icao visibility
             $visibility->setChunk(trim($found[1]));
             $visibility->setVisibility(Value::newIntValue($found[2], Value::METER));
             if ($found[4] != null) {
                 $visibility->setMinimumVisibility(Value::newIntValue($found[5], Value::METER))->setMinimumVisibilityDirection($found[6]);
             }
             $visibility->setNDV($found[3] != null);
         } else {
             // us visibility
             $main = intval($found[7]);
             $frac_top = intval($found[9]);
             $frac_bot = intval($found[10]);
             if ($frac_bot != 0) {
                 $vis_value = $main + $frac_top / $frac_bot;
             } else {
                 $vis_value = $main;
             }
             $visibility->setChunk(trim($found[1]));
             $visibility->setVisibility(Value::newValue($vis_value, Value::STATUTE_MILE));
         }
     }
     // return result + remaining metar
     return array('result' => array('cavok' => $cavok, 'visibility' => $visibility), 'remaining_metar' => $new_remaining_metar);
 }
 public function parse($remaining_metar, $cavok = false)
 {
     $result = $this->consume($remaining_metar);
     $found = $result['found'];
     $new_remaining_metar = $result['remaining'];
     // handle the case where nothing has been found
     if ($found == null) {
         $result = null;
     } else {
         // iterate on the results to get all runways visual range found
         $runways = array();
         for ($i = 1; $i <= 20; $i += 7) {
             if ($found[$i] != null) {
                 // check runway qfu validity
                 $qfu_as_int = Value::toInt($found[$i + 1]);
                 if ($qfu_as_int > 36 || $qfu_as_int < 1) {
                     throw new ChunkDecoderException($remaining_metar, $new_remaining_metar, 'Invalid runway QFU runway visual range information', $this);
                 }
                 // get distance unit
                 if ($found[$i + 5] == 'FT') {
                     $range_unit = Value::FEET;
                 } else {
                     $range_unit = Value::METER;
                 }
                 $observation = new RunwayVisualRange();
                 $observation->setChunk(trim($found[$i]));
                 $observation->setRunway($found[$i + 1])->setPastTendency($found[$i + 6]);
                 if ($found[$i + 3] != null) {
                     $interval = array(Value::newIntValue($found[$i + 3], $range_unit), Value::newIntValue($found[$i + 4], $range_unit));
                     $observation->setVariable(true)->setVisualRangeInterval($interval);
                 } else {
                     $observation->setVariable(false)->setVisualRange(Value::newIntValue($found[$i + 4], $range_unit));
                 }
                 $runways[] = $observation;
             }
         }
         $result = array('runwaysVisualRange' => $runways);
     }
     // return result + remaining metar
     return array('result' => $result, 'remaining_metar' => $new_remaining_metar);
 }
 public function parse($remaining_metar, $cavok = false)
 {
     $result = $this->consume($remaining_metar);
     $found = $result['found'];
     $new_remaining_metar = $result['remaining'];
     // handle the case where nothing has been found
     if ($found == null) {
         $result = null;
     } else {
         // retrieve found params
         $air_temp = Value::newIntValue($found[1], Value::DEGREE_CELSIUS);
         if ($found[2] == null) {
             $dew_point_temp = null;
         } else {
             $dew_point_temp = Value::newIntValue($found[2], Value::DEGREE_CELSIUS);
         }
         $result = array('airTemperature' => $air_temp, 'dewPointTemperature' => $dew_point_temp);
     }
     // return result + remaining metar
     return array('result' => $result, 'remaining_metar' => $new_remaining_metar);
 }