Cleanup SI Unit classes and interface for REST responses; fixes to a few METAR parsing issues

This commit is contained in:
Nabeel Shahzad 2019-07-15 15:14:40 -04:00
parent 466d04caf7
commit 06d8f11ca3
33 changed files with 399 additions and 222 deletions

View File

@ -2,11 +2,7 @@
namespace App\Http\Resources;
use App\Support\Units\Distance;
use App\Support\Units\Fuel;
use Illuminate\Http\Resources\Json\Resource;
class Acars extends Resource
class Acars extends Response
{
/**
* Transform the resource into an array.
@ -17,16 +13,13 @@ class Acars extends Resource
*/
public function toArray($request)
{
$obj = parent::toArray($request);
$res = parent::toArray($request);
if ($this->distance instanceof Distance) {
$obj['distance'] = $this->distance->units;
}
$this->checkUnitFields($res, [
'distance',
'fuel',
]);
if ($this->fuel instanceof Fuel) {
$obj['fuel'] = $this->fuel->units;
}
return $obj;
return $res;
}
}

View File

@ -2,12 +2,10 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
/**
* ACARS table but only include the fields for the routes
* Class AcarsRoute
*/
class AcarsLog extends Resource
class AcarsLog extends Response
{
}

View File

@ -2,12 +2,10 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
/**
* ACARS table but only include the fields for the routes
* Class AcarsRoute
*/
class AcarsRoute extends Resource
class AcarsRoute extends Response
{
}

View File

@ -2,8 +2,6 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Aircraft extends Resource
class Aircraft extends Response
{
}

View File

@ -2,9 +2,7 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Airline extends Resource
class Airline extends Response
{
public function toArray($request)
{

View File

@ -2,8 +2,6 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Airport extends Resource
class Airport extends Response
{
}

View File

@ -2,9 +2,7 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Award extends Resource
class Award extends Response
{
public function toArray($request)
{

View File

@ -2,15 +2,13 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Bid extends Resource
class Bid extends Response
{
public function toArray($request)
{
$bid = parent::toArray($request);
$bid['flight'] = new Flight($this->flight);
$res = parent::toArray($request);
$res['flight'] = new Flight($this->flight);
return $bid;
return $res;
}
}

View File

@ -3,9 +3,8 @@
namespace App\Http\Resources;
use App\Support\Units\Distance;
use Illuminate\Http\Resources\Json\Resource;
class Flight extends Resource
class Flight extends Response
{
/**
* Set the fields on the flight object
@ -24,19 +23,19 @@ class Flight extends Resource
public function toArray($request)
{
$flight = parent::toArray($request);
$res = parent::toArray($request);
$flight['ident'] = $this->ident;
$res['ident'] = $this->ident;
// Return multiple measures so the client can pick what they want
if ($this->distance instanceof Distance) {
$flight['distance'] = $this->distance->units;
}
$this->checkUnitFields($res, [
'distance',
]);
$flight['airline'] = new Airline($this->airline);
$flight['subfleets'] = Subfleet::collection($this->subfleets);
$flight['fields'] = $this->setFields();
$res['airline'] = new Airline($this->airline);
$res['subfleets'] = Subfleet::collection($this->subfleets);
$res['fields'] = $this->setFields();
return $flight;
return $res;
}
}

View File

@ -2,9 +2,7 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class JournalTransaction extends Resource
class JournalTransaction extends Response
{
public function toArray($request)
{

View File

@ -9,16 +9,16 @@ class Navdata extends Resource
{
public function toArray($request)
{
$point = parent::toArray($request);
$res = parent::toArray($request);
// Some details about the navaid type
$type = [
'type' => $point['type'],
'name' => NavaidType::label($point['type']),
'type' => $res['type'],
'name' => NavaidType::label($res['type']),
];
$point['type'] = $type;
$res['type'] = $type;
return $point;
return $res;
}
}

View File

@ -18,12 +18,12 @@ class News extends Resource
*/
public function toArray($request)
{
$resp = parent::toArray($request);
$resp['user'] = [
$res = parent::toArray($request);
$res['user'] = [
'id' => $this->user->id,
'name' => $this->user->name,
];
return $resp;
return $res;
}
}

View File

@ -3,11 +3,8 @@
namespace App\Http\Resources;
use App\Models\Enums\PirepStatus;
use App\Support\Units\Distance;
use App\Support\Units\Fuel;
use Illuminate\Http\Resources\Json\Resource;
class Pirep extends Resource
class Pirep extends Response
{
/**
* Transform the resource into an array.
@ -18,43 +15,36 @@ class Pirep extends Resource
*/
public function toArray($request)
{
$pirep = parent::toArray($request);
$res = parent::toArray($request);
$res['ident'] = $this->ident;
$pirep['ident'] = $this->ident;
if ($this->distance instanceof Distance) {
$pirep['distance'] = $this->distance->units;
}
if ($this->fuel_used instanceof Fuel) {
$pirep['fuel_used'] = $this->fuel_used->units;
}
if ($this->planned_distance instanceof Distance) {
$pirep['planned_distance'] = $this->planned_distance->units;
}
$this->checkUnitFields($res, [
'distance',
'fuel_used',
'planned_distance',
]);
/*
* Relationship fields
*/
if ($this->block_on_time) {
$pirep['block_on_time'] = $this->block_on_time->toIso8601ZuluString();
$res['block_on_time'] = $this->block_on_time->toIso8601ZuluString();
}
if ($this->block_off_time) {
$pirep['block_off_time'] = $this->block_off_time->toIso8601ZuluString();
$res['block_off_time'] = $this->block_off_time->toIso8601ZuluString();
}
$pirep['status_text'] = PirepStatus::label($this->status);
$res['status_text'] = PirepStatus::label($this->status);
$pirep['airline'] = new Airline($this->airline);
$pirep['dpt_airport'] = new Airport($this->dpt_airport);
$pirep['arr_airport'] = new Airport($this->arr_airport);
$res['airline'] = new Airline($this->airline);
$res['dpt_airport'] = new Airport($this->dpt_airport);
$res['arr_airport'] = new Airport($this->arr_airport);
$pirep['position'] = new Acars($this->position);
$pirep['comments'] = PirepComment::collection($this->comments);
$pirep['user'] = [
$res['position'] = new Acars($this->position);
$res['comments'] = PirepComment::collection($this->comments);
$res['user'] = [
'id' => $this->user->id,
'name' => $this->user->name,
'home_airport_id' => $this->user->home_airport_id,
@ -62,8 +52,8 @@ class Pirep extends Resource
];
// format to kvp
$pirep['fields'] = new PirepFieldCollection($this->fields);
$res['fields'] = new PirepFieldCollection($this->fields);
return $pirep;
return $res;
}
}

View File

@ -11,11 +11,11 @@ class PirepFieldCollection extends ResourceCollection
{
public function toArray($request)
{
$obj = [];
$res = [];
foreach ($this->collection as $field) {
$obj[$field->name] = $field->value;
$res[$field->name] = $field->value;
}
return $obj;
return $res;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Http\Resources;
use App\Interfaces\Unit;
use Illuminate\Http\Resources\Json\Resource;
/**
@ -9,4 +10,22 @@ use Illuminate\Http\Resources\Json\Resource;
*/
class Response extends Resource
{
/**
* Iterate through the list of $fields and check if they're a "Unit"
* If they are, then add the response
*
* @param $response
* @param array $fields
*/
public function checkUnitFields(&$response, array $fields): void
{
foreach ($fields as $f) {
if ($this->{$f} instanceof Unit) {
$response[$f] = $this->{$f}->getResponseUnits();
} else {
$response[$f] = $this->{$f};
}
}
}
}

View File

@ -8,9 +8,9 @@ class Subfleet extends Resource
{
public function toArray($request)
{
$arr = parent::toArray($request);
$arr['aircraft'] = Aircraft::collection($this->aircraft);
$res = parent::toArray($request);
$res['aircraft'] = Aircraft::collection($this->aircraft);
return $arr;
return $res;
}
}

View File

@ -20,18 +20,19 @@ class Unit implements ArrayAccess
/**
* All of the units of this class
*
* @var array
*/
public $units;
/**
* Holds an instance of the PhpUnit type
*
* @var
*/
protected $instance;
/**
* Units that are included as part of the REST response
*/
public $responseUnits = [];
/**
* @return mixed
*/
@ -40,6 +41,31 @@ class Unit implements ArrayAccess
return $this->__toString();
}
/**
* Just call toUnit() on the PhpUnitOfMeasure instance
*
* @param string $unit
*
* @return mixed
*/
public function toUnit($unit)
{
return $this->instance->toUnit($unit);
}
/**
* Return all of the units that get sent back in a response
*/
public function getResponseUnits(): array
{
$response = [];
foreach ($this->responseUnits as $unit) {
$response[$unit] = $this[$unit];
}
return $response;
}
/**
* Implements ArrayAccess
*
@ -61,7 +87,7 @@ class Unit implements ArrayAccess
*/
public function offsetGet($offset)
{
return $this->units[$offset];
return round($this->instance->toUnit($offset), 2);
}
/**
@ -72,7 +98,7 @@ class Unit implements ArrayAccess
*/
public function offsetSet($offset, $value)
{
$this->units[$offset] = $value;
// $this->units[$offset] = $value;
}
/**
@ -82,7 +108,7 @@ class Unit implements ArrayAccess
*/
public function offsetUnset($offset)
{
$this->units[$offset] = null;
// $this->units[$offset] = null;
}
/**

View File

@ -133,9 +133,9 @@ class Flight extends Model
}
/**
* Return a new Length unit so conversions can be made
* Return a new Distance unit so conversions can be made
*
* @return int|Distance
* @return Distance
*/
public function getDistanceAttribute()
{
@ -148,9 +148,9 @@ class Flight extends Model
return new Distance($distance, config('phpvms.internal_units.distance'));
} catch (NonNumericValue $e) {
return 0;
return new Distance(0, config('phpvms.internal_units.distance', 'nmi'));
} catch (NonStringUnitName $e) {
return 0;
return new Distance(0, config('phpvms.internal_units.distance', 'nmi'));
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace App\Providers;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;
use PhpUnitsOfMeasure\Exception\DuplicateUnitNameOrAlias;
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
use PhpUnitsOfMeasure\Exception\UnknownUnitOfMeasure;
use PhpUnitsOfMeasure\PhysicalQuantity\Length;
use PhpUnitsOfMeasure\PhysicalQuantity\Temperature;
use PhpUnitsOfMeasure\UnitOfMeasure;
/**
* Add new measurement units to PhpUnitsOfMeasure
*/
class MeasurementsProvider extends ServiceProvider
{
public function boot(): void
{
try {
$this->addTemperatures();
} catch (Exception $e) {
Log::error($e);
}
}
/**
* Add lowercase temperature units
*
* @throws NonStringUnitName
* @throws UnknownUnitOfMeasure
*/
protected function addTemperatures()
{
$fUnit = Temperature::getUnit('F');
$fUnit->addAlias('f');
$cUnit = Temperature::getUnit('C');
$cUnit->addAlias('c');
}
}

View File

@ -4,7 +4,11 @@ namespace App\Support;
use App\Support\Units\Altitude;
use App\Support\Units\Distance;
use App\Support\Units\Pressure;
use App\Support\Units\Temperature;
use App\Support\Units\Velocity;
use PhpUnitsOfMeasure\Exception\NonNumericValue;
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
/**
* Class Metar
@ -388,6 +392,87 @@ class Metar implements \ArrayAccess
if (isset($this->result[$parameter])) {
return $this->result[$parameter];
}
return null;
}
/**
* Return an Altitude value or object
*
* @param int|float $value
* @param string $unit "feet" or "meters"
*
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return Altitude
*/
protected function createAltitude($value, $unit)
{
return new Altitude($value, $unit);
}
/**
* Return a Distance value or object
*
* @param int|float $value
* @param string $unit "m" (meters) or "mi" (miles)
*
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return Distance
*/
protected function createDistance($value, $unit)
{
return new Distance($value, $unit);
}
/**
* Return a Pressure value or object
*
* @param int|float $value
* @param string $unit "F" or "C"
*
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return Pressure
*/
protected function createPressure($value, $unit)
{
return new Pressure($value, $unit);
}
/**
* Return a Temperature value or object
*
* @param int|float $value
* @param string $unit "F" or "C"
*
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return Temperature
*/
protected function createTemperature($value, $unit)
{
return new Temperature($value, $unit);
}
/**
* Create a new velocity unit
* @param int|float $value
* @param string $unit "knots", "km/hour", "m/s"
*
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return Velocity
*/
protected function createVelocity($value, $unit)
{
return new Velocity($value, $unit);
}
/**
@ -591,6 +676,8 @@ class Metar implements \ArrayAccess
* Decodes station code.
*
* @param mixed $part
*
* @return bool
*/
private function get_station($part)
{
@ -609,6 +696,8 @@ class Metar implements \ArrayAccess
* Format is ddhhmmZ where dd = day, hh = hours, mm = minutes in UTC time.
*
* @param mixed $part
*
* @return bool
*/
private function get_time($part)
{
@ -648,6 +737,8 @@ class Metar implements \ArrayAccess
* Ignore station type if present.
*
* @param mixed $part
*
* @return bool
*/
private function get_station_type($part)
{
@ -750,8 +841,8 @@ class Metar implements \ArrayAccess
*
* @param mixed $part
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return bool
*/
@ -772,7 +863,7 @@ class Metar implements \ArrayAccess
// Cloud and visibilty OK or ICAO visibilty greater than 10 km
if ($found[1] === 'CAVOK' || $found[1] === '9999') {
$this->set_result_value('visibility', new Distance(10000, 'm'));
$this->set_result_value('visibility', $this->createDistance(10000, 'm'));
$this->set_result_value('visibility_report', 'Greater than 10 km');
/* @noinspection NotOptimalIfConditionsInspection */
if ($found[1] === 'CAVOK') {
@ -787,7 +878,7 @@ class Metar implements \ArrayAccess
// ICAO visibility (in meters)
if (isset($found[2]) && !empty($found[2])) {
$visibility = new Distance((int) $found[2], 'm');
$visibility = $this->createDistance((int)$found[2], 'm');
} // US visibility (in miles)
else {
if (isset($found[3]) && !empty($found[3])) {
@ -800,7 +891,7 @@ class Metar implements \ArrayAccess
$visibility = (int) $found[4];
}
$visibility = new Distance($visibility, 'mi');
$visibility = $this->createDistance($visibility, 'mi');
}
$unit = ' meters';
@ -824,9 +915,9 @@ class Metar implements \ArrayAccess
*
* @param $part
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws NonStringUnitName
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return bool
*/
@ -836,7 +927,7 @@ class Metar implements \ArrayAccess
return false;
}
$meters = new Distance((int) $found[1], 'm');
$meters = $this->createDistance((int)$found[1], 'm');
$this->set_result_value('visibility_min', $meters);
if (isset($found[2]) && !empty($found[2])) {
@ -854,8 +945,8 @@ class Metar implements \ArrayAccess
*
* @param $part
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return bool
*/
@ -899,13 +990,13 @@ class Metar implements \ArrayAccess
// Runway visual range
if (isset($found[6])) {
if (!empty($found[4])) {
$observed['interval_min'] = new Distance($found[4], $unit);
$observed['interval_max'] = new Distance($found[6], $unit);
$observed['interval_min'] = $this->createDistance($found[4], $unit);
$observed['interval_max'] = $this->createDistance($found[6], $unit);
if (!empty($found[5])) {
$observed['variable_prefix'] = $found[5];
}
} else {
$observed['variable'] = new Distance($found[6], $unit);
$observed['variable'] = $this->createDistance($found[6], $unit);
}
}
@ -960,8 +1051,8 @@ class Metar implements \ArrayAccess
*
* @param $part
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return bool
*/
@ -990,7 +1081,7 @@ class Metar implements \ArrayAccess
}
} // Cloud cover observed
elseif (isset($found[5]) && !empty($found[5]) && is_numeric($found[5])) {
$observed['height'] = new Altitude($found[5] * 100, 'feet');
$observed['height'] = $this->createAltitude($found[5] * 100, 'feet');
// Cloud height
if (null === $this->result['cloud_height']['m'] || $observed['height']['m'] < $this->result['cloud_height']['m']) {
@ -1047,8 +1138,10 @@ class Metar implements \ArrayAccess
*
* @param mixed $part
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return bool
*/
private function get_temperature($part)
{
@ -1065,20 +1158,20 @@ class Metar implements \ArrayAccess
// Temperature
$temperature_c = (int) str_replace('M', '-', $found[1]);
$temperature = new Temperature($temperature_c, 'C');
$temperature = $this->createTemperature($temperature_c, 'C');
$this->set_result_value('temperature', $temperature);
$this->calculate_wind_chill($temperature['f']);
$this->calculate_wind_chill($temperature['F']);
// Dew point
if (isset($found[2]) && '' !== $found[2] && $found[2] !== 'XX') {
$dew_point_c = (int) str_replace('M', '-', $found[2]);
$dew_point = new Temperature($dew_point_c, 'C');
$dew_point = $this->createTemperature($dew_point_c, 'C');
$rh = round(100 * (((112 - (0.1 * $temperature_c) + $dew_point_c) / (112 + (0.9 * $temperature_c))) ** 8));
$this->set_result_value('dew_point', $dew_point);
$this->set_result_value('humidity', $rh);
$this->calculate_heat_index($temperature['f'], $rh);
$this->calculate_heat_index($temperature['F'], $rh);
}
$this->method++;
@ -1096,21 +1189,26 @@ class Metar implements \ArrayAccess
* 1 lb/sq in = 0.491154 in Hg = 0.014504 hPa
* 1 atm = 0.33421 in Hg = 0.0009869 hPa
*
*
* @param mixed $part
*
* @throws NonNumericValue
* @throws NonStringUnitName
*
* @return bool
*/
private function get_pressure($part)
{
if (!preg_match('@^(Q|A)(////|[\d]{4})@', $part, $found)) {
return false;
}
$pressure = (int) $found[2];
if ($found[1] === 'A') {
$pressure /= 100;
}
$this->set_result_value('barometer', $pressure); // units are hPa
$this->set_result_value('barometer_mb', $pressure); // units are hPa
$this->set_result_value('barometer_in', round(0.02953 * $pressure, 2)); // convert to in Hg
$this->set_result_value('barometer', $this->createPressure($pressure, 'hPa'));
$this->method++;
return true;
@ -1121,6 +1219,8 @@ class Metar implements \ArrayAccess
* Format is REww where ww = Weather phenomenon code (see get_present_weather above).
*
* @param mixed $part
*
* @return bool
*/
private function get_recent_weather($part)
{
@ -1133,6 +1233,8 @@ class Metar implements \ArrayAccess
* C = extent of deposit, ee = depth of deposit, BB = friction coefficient.
*
* @param mixed $part
*
* @return bool
*/
private function get_runways_report($part)
{
@ -1241,6 +1343,8 @@ class Metar implements \ArrayAccess
* Format is 'WS ALL RWY' or 'WS RWYdd' where dd = Runway designator (see get_runway_vr above).
*
* @param mixed $part
*
* @return bool
*/
private function get_wind_shear($part)
{
@ -1289,8 +1393,8 @@ class Metar implements \ArrayAccess
* HH - Forecast hour, i.e. the time(hour) when the temperature is expected
* Z - Time Zone indicator, Z=GMT.
*
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return bool
*/
@ -1307,7 +1411,7 @@ class Metar implements \ArrayAccess
// Temperature
$temperature_c = (int) str_replace('M', '-', $found[2]);
$temperture = new Temperature($temperature_c, 'C');
$temperture = $this->createTemperature($temperature_c, 'C');
$forecast = [
'value' => $temperture,
@ -1336,6 +1440,8 @@ class Metar implements \ArrayAccess
* LTDDhhmm or DDhh/DDhh, where hh = hours, mm = minutes, DD = day of month.
*
* @param mixed $part
*
* @return bool
*/
private function get_trends($part)
{
@ -1608,8 +1714,8 @@ class Metar implements \ArrayAccess
* @param $temperature_f
* @param $rh
*
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws NonNumericValue
* @throws NonStringUnitName
*/
private function calculate_heat_index($temperature_f, $rh): void
{
@ -1621,7 +1727,7 @@ class Metar implements \ArrayAccess
$hi_f = round($hi_f);
$hi_c = round(($hi_f - 32) / 1.8);
$this->set_result_value('heat_index', new Temperature($hi_c, 'C'));
$this->set_result_value('heat_index', $this->createTemperature($hi_c, 'C'));
}
}
@ -1631,20 +1737,20 @@ class Metar implements \ArrayAccess
*
* @param $temperature_f
*
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
* @throws NonNumericValue
* @throws NonStringUnitName
*/
private function calculate_wind_chill($temperature_f): void
{
if ($temperature_f < 51 && $this->result['wind_speed'] !== 0) {
$windspeed = round(2.23694 * $this->result['wind_speed']); // convert m/s to mi/h
$windspeed = $this->result['wind_speed']->toUnit('mph');
if ($windspeed > 3) {
$chill_f = 35.74 + 0.6215 * $temperature_f - 35.75 * ($windspeed ** 0.16);
$chill_f += 0.4275 * $temperature_f * ($windspeed ** 0.16);
$chill_f = round($chill_f);
$chill_c = round(($chill_f - 32) / 1.8);
$this->set_result_value('wind_chill', new Temperature($chill_c, 'C'));
$this->set_result_value('wind_chill', $this->createTemperature($chill_c, 'C'));
}
}
}
@ -1661,7 +1767,10 @@ class Metar implements \ArrayAccess
* @param $speed
* @param $unit
*
* @return float|null
* @throws NonStringUnitName
* @throws NonNumericValue
*
* @return Velocity
*/
private function convert_speed($speed, $unit)
{
@ -1669,36 +1778,11 @@ class Metar implements \ArrayAccess
switch ($unit) {
case 'KT':
return round(0.514444 * $speed, 2); // from knots
return $this->createVelocity($speed, 'knots');
case 'KPH':
return round(0.277778 * $speed, 2); // from km/h
case 'MPS':
return round($speed, 2); // m/s
}
}
/**
* Convert distance into meters.
* Some other common conversion factors:
* 1 m = 3.28084 ft = 0.00062 mi
* 1 ft = 0.3048 m = 0.00019 mi
* 1 mi = 5279.99 ft = 1609.34 m
*
* @param $distance
* @param $unit
*
* @return float|null
*/
private function convert_distance($distance, $unit)
{
// TODO: return dict w/ multiple units - NS
switch ($unit) {
case 'FT':
return round(0.3048 * $distance); // from ft.
case 'SM':
return round(1609.34 * $distance); // from miles
case 'M':
return round($distance); // meters
return $this->createVelocity($speed, 'km/hour');
default:
return $this->createVelocity($speed, 'm/s');
}
}
@ -1706,12 +1790,16 @@ class Metar implements \ArrayAccess
* Convert direction degrees to compass label.
*
* @param mixed $direction
*
* @return string Direction string
*/
private function convert_direction_label($direction)
private function convert_direction_label($direction): string
{
if ($direction >= 0 && $direction <= 360) {
return static::$direction_codes[round($direction / 22.5) % 16];
}
return 'N';
}
/**

View File

@ -7,6 +7,12 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Length;
class Altitude extends Unit
{
public $responseUnits = [
'ft',
'km',
'm',
];
/**
* @param float $value
* @param string $unit
@ -18,11 +24,5 @@ class Altitude extends Unit
{
$this->unit = setting('units.altitude');
$this->instance = new Length($value, $unit);
$this->units = [
'm' => round($this->instance->toUnit('meters'), 2),
'km' => round($this->instance->toUnit('meters') / 1000, 2),
'ft' => round($this->instance->toUnit('feet'), 2),
];
}
}

View File

@ -7,6 +7,12 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Length;
class Distance extends Unit
{
public $responseUnits = [
'km',
'mi',
'nmi',
];
/**
* Distance constructor.
*
@ -20,12 +26,5 @@ class Distance extends Unit
{
$this->unit = setting('units.distance');
$this->instance = new Length($value, $unit);
$this->units = [
'mi' => round($this->instance->toUnit('miles'), 2),
'nmi' => round($this->instance->toUnit('nmi'), 2),
'm' => round($this->instance->toUnit('meters'), 2),
'km' => round($this->instance->toUnit('meters') / 1000, 2),
];
}
}

View File

@ -7,6 +7,11 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Mass;
class Fuel extends Unit
{
public $responseUnits = [
'kg',
'lbs',
];
/**
* @param float $value
* @param string $unit
@ -18,10 +23,5 @@ class Fuel extends Unit
{
$this->unit = setting('units.fuel');
$this->instance = new Mass($value, $unit);
$this->units = [
'kg' => round($this->instance->toUnit('kg'), 2),
'lbs' => round($this->instance->toUnit('lbs'), 2),
];
}
}

View File

@ -7,6 +7,11 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Mass as MassUnit;
class Mass extends Unit
{
public $responseUnits = [
'kg',
'lbs',
];
/**
* @param float $value
* @param string $unit
@ -18,10 +23,5 @@ class Mass extends Unit
{
$this->unit = setting('units.weight');
$this->instance = new MassUnit($value, $unit);
$this->units = [
'kg' => round($this->instance->toUnit('kg'), 2),
'lbs' => round($this->instance->toUnit('lbs'), 2),
];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Support\Units;
use App\Interfaces\Unit;
use PhpUnitsOfMeasure\PhysicalQuantity\Pressure as PressureUnit;
/**
* Composition for the converter
*/
class Pressure extends Unit
{
public $responseUnits = [
'atm',
'hPa',
];
/**
* @param float $value
* @param string $unit
*
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
*/
public function __construct(float $value, string $unit)
{
$this->unit = setting('units.temperature');
$this->instance = new PressureUnit($value, $unit);
}
}

View File

@ -10,6 +10,11 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Temperature as TemperatureUnit;
*/
class Temperature extends Unit
{
public $responseUnits = [
'C',
'F',
];
/**
* @param float $value
* @param string $unit
@ -21,12 +26,5 @@ class Temperature extends Unit
{
$this->unit = setting('units.temperature');
$this->instance = new TemperatureUnit($value, $unit);
$this->units = [
'F' => round($this->instance->toUnit('F'), 2),
'f' => round($this->instance->toUnit('F'), 2),
'C' => round($this->instance->toUnit('C'), 2),
'c' => round($this->instance->toUnit('C'), 2),
];
}
}

View File

@ -10,6 +10,11 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Velocity as VelocityUnit;
*/
class Velocity extends Unit
{
public $responseUnits = [
'km/h',
'knots',
];
/**
* @param float $value
* @param string $unit
@ -21,10 +26,5 @@ class Velocity extends Unit
{
$this->unit = setting('units.speed');
$this->instance = new VelocityUnit($value, $unit);
$this->units = [
'knots' => round($this->instance->toUnit('knots'), 2),
'km/h' => round($this->instance->toUnit('km/h'), 2),
];
}
}

View File

@ -10,6 +10,11 @@ use PhpUnitsOfMeasure\PhysicalQuantity\Volume as VolumeUnit;
*/
class Volume extends Unit
{
public $responseUnits = [
'gal',
'liters',
];
/**
* @param float $value
* @param string $unit
@ -21,10 +26,5 @@ class Volume extends Unit
{
$this->unit = setting('units.volume');
$this->instance = new VolumeUnit($value, $unit);
$this->units = [
'gal' => round($this->instance->toUnit('gal'), 2),
'liters' => round($this->instance->toUnit('liters'), 2),
];
}
}

View File

@ -86,6 +86,7 @@ return [
App\Providers\RouteServiceProvider::class,
App\Providers\vaCentralServiceProvider::class,
App\Providers\ExtendedTimezonelistProvider::class,
App\Providers\MeasurementsProvider::class,
],
'aliases' => [

View File

@ -277,7 +277,7 @@ class AcarsTest extends TestCase
$aircraft = $subfleet['aircraft']->random();
$uri = '/api/pireps/prefile';
$pirep = [
$pirep_create = [
'airline_id' => $airline->id,
'aircraft_id' => $aircraft->id,
'dpt_airport_id' => $airport->icao,
@ -293,7 +293,7 @@ class AcarsTest extends TestCase
],
];
$response = $this->post($uri, $pirep);
$response = $this->post($uri, $pirep_create);
$response->assertStatus(201);
// Get the PIREP ID
@ -314,7 +314,7 @@ class AcarsTest extends TestCase
*/
$this->assertHasKeys($pirep, ['fields']);
$this->assertEquals('custom_value', $pirep['fields']['custom_field']);
$this->assertEquals($pirep_create['planned_distance'], $pirep['planned_distance']['nmi']);
$this->assertHasKeys($pirep['planned_distance'], ['mi', 'nmi', 'km']);
/**

View File

@ -466,7 +466,7 @@ class ImporterTest extends TestCase
$this->assertEquals('0810 CST', $flight->dpt_time);
$this->assertEquals('1235 EST', $flight->arr_time);
$this->assertEquals('350', $flight->level);
$this->assertEquals('1477', $flight->distance);
$this->assertEquals(1477, $flight->distance['nmi']);
$this->assertEquals('207', $flight->flight_time);
$this->assertEquals(FlightType::SCHED_PAX, $flight->flight_type);
$this->assertEquals('ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6', $flight->route);

View File

@ -1,6 +1,7 @@
<?php
use App\Support\Math;
use App\Support\Units\Distance;
class MathTest extends TestCase
{
@ -26,4 +27,11 @@ class MathTest extends TestCase
$this->assertEquals($test['expected'], $test['fn']);
}
}
public function testDistanceMeasurement()
{
$dist = new Distance(1, 'mi');
$this->assertEquals(1609.34, $dist['m']);
$this->assertEquals(1.61, $dist['km']);
}
}

View File

@ -50,8 +50,8 @@ class MetarTest extends TestCase
$this->assertEquals('KJFK', $parsed['station']);
$this->assertEquals(4, $parsed['observed_day']);
$this->assertEquals('21:51 UTC', $parsed['observed_time']);
$this->assertEquals(13.38, $parsed['wind_speed']);
$this->assertEquals(20.06, $parsed['wind_gust_speed']);
$this->assertEquals(26, $parsed['wind_speed']['knots']);
$this->assertEquals(39, $parsed['wind_gust_speed']['knots']);
$this->assertEquals(280, $parsed['wind_direction']);
$this->assertEquals('W', $parsed['wind_direction_label']);
$this->assertEquals(false, $parsed['wind_direction_varies']);
@ -72,8 +72,7 @@ class MetarTest extends TestCase
$this->assertEquals(24.8, $parsed['dew_point']['f']);
$this->assertEquals(33, $parsed['humidity']);
$this->assertEquals(29.58, $parsed['barometer']);
$this->assertEquals(0.87, $parsed['barometer_in']);
$this->assertEquals(29.58, $parsed['barometer']['hPa']);
$this->assertEquals('AO2 PK WND 27045/2128 PRESRR SLP018 T01221044', $parsed['remarks']);
}
@ -121,7 +120,7 @@ class MetarTest extends TestCase
$parsed = Metar::parse($metar);
$this->assertEquals('VFR', $parsed['category']);
$this->assertEquals(9.26, $parsed['wind_speed']);
$this->assertEquals(18, $parsed['wind_speed']['knots']);
$this->assertEquals(8, $parsed['visibility']['mi']);
$this->assertEquals(
'Scattered at 4500 feet, cumulonimbus; broken sky at 6000 feet; overcast sky at 8000 feet',