Compare commits

..
Author SHA1 Message Date
Nabeel Shahzad c97977de9a Include all enums in aliases 2021-01-25 17:07:11 -05:00
Nabeel Shahzad bda1a91117 Return null on empty value 2021-01-25 17:03:48 -05:00
Nabeel Shahzad 3f92191126 Tests for the CSV import fix
#1007
2021-01-25 16:49:32 -05:00
44 changed files with 141 additions and 463 deletions
+5 -49
View File
@@ -12,24 +12,13 @@ abstract class Metar
{ {
/** /**
* Implement retrieving the METAR - return the METAR string. Needs to be protected, * Implement retrieving the METAR - return the METAR string. Needs to be protected,
* since this shouldn't be directly called. Call `metar($icao)`. If not implemented, * since this shouldn't be directly called. Call `get_metar($icao)` instead
* return a blank string
* *
* @param $icao * @param $icao
* *
* @return mixed * @return mixed
*/ */
abstract protected function get_metar($icao): string; abstract protected function metar($icao): string;
/**
* Implement retrieving the TAF - return the string. Call `taf($icao)`. If not implemented,
* return a blank string
*
* @param $icao
*
* @return mixed
*/
abstract protected function get_taf($icao): string;
/** /**
* Download the METAR, wrap in caching * Download the METAR, wrap in caching
@@ -38,9 +27,9 @@ abstract class Metar
* *
* @return string * @return string
*/ */
public function metar($icao): string public function get_metar($icao): string
{ {
$cache = config('cache.keys.METAR_WEATHER_LOOKUP'); $cache = config('cache.keys.WEATHER_LOOKUP');
$key = $cache['key'].$icao; $key = $cache['key'].$icao;
if (Cache::has($key)) { if (Cache::has($key)) {
@@ -51,7 +40,7 @@ abstract class Metar
} }
try { try {
$raw_metar = $this->get_metar($icao); $raw_metar = $this->metar($icao);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error('Error getting METAR: '.$e->getMessage(), $e->getTrace()); Log::error('Error getting METAR: '.$e->getMessage(), $e->getTrace());
return ''; return '';
@@ -63,37 +52,4 @@ abstract class Metar
return $raw_metar; return $raw_metar;
} }
/**
* Download the TAF, wrap in caching
*
* @param $icao
*
* @return string
*/
public function taf($icao): string
{
$cache = config('cache.keys.TAF_WEATHER_LOOKUP');
$key = $cache['key'].$icao;
if (Cache::has($key)) {
$taf = Cache::get($key);
if ($taf !== '') {
return $taf;
}
}
try {
$taf = $this->get_taf($icao);
} catch (\Exception $e) {
Log::error('Error getting TAF: '.$e->getMessage(), $e->getTrace());
return '';
}
if ($taf !== '') {
Cache::put($key, $taf, $cache['time']);
}
return $taf;
}
} }
+11 -4
View File
@@ -4,8 +4,10 @@ namespace App\Cron\Nightly;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\CronNightly; use App\Events\CronNightly;
use App\Models\Enums\UserState;
use App\Models\User;
use App\Services\UserService; use App\Services\UserService;
use Illuminate\Support\Facades\Log; use Carbon\Carbon;
/** /**
* Determine if any pilots should be set to ON LEAVE status * Determine if any pilots should be set to ON LEAVE status
@@ -16,8 +18,6 @@ class PilotLeave extends Listener
/** /**
* PilotLeave constructor. * PilotLeave constructor.
*
* @param UserService $userSvc
*/ */
public function __construct(UserService $userSvc) public function __construct(UserService $userSvc)
{ {
@@ -34,7 +34,14 @@ class PilotLeave extends Listener
*/ */
public function handle(CronNightly $event): void public function handle(CronNightly $event): void
{ {
$users = $this->userSvc->findUsersOnLeave(); if (setting('pilots.auto_leave_days') === 0) {
return;
}
$date = Carbon::now()->subDay(setting('pilots.auto_leave_days'));
$users = User::where('status', UserState::ACTIVE)
->whereDate('updated_at', '<', $date);
foreach ($users as $user) { foreach ($users as $user) {
Log::info('Setting user '.$user->ident.' to ON LEAVE status'); Log::info('Setting user '.$user->ident.' to ON LEAVE status');
$this->userSvc->setStatusOnLeave($user); $this->userSvc->setStatusOnLeave($user);
@@ -1,18 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Change the vertical speed for the acars table to a double
*/
class ChangeAcarsVsType extends Migration
{
public function up()
{
Schema::table('acars', function (Blueprint $table) {
$table->float('vs')->change()->default(0.0)->nullable();
});
}
}
@@ -1,19 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Bring the sessions table in line with the latest
*/
class UpdateSessionsTable extends Migration
{
public function up()
{
Schema::table('sessions', function (Blueprint $table) {
$table->index('user_id');
$table->index('last_activity');
});
}
}
@@ -186,13 +186,13 @@ class AwardController extends Controller
{ {
$award = $this->awardRepository->findWithoutFail($id); $award = $this->awardRepository->findWithoutFail($id);
if (empty($award)) { if (empty($award)) {
Flash::error('Award not found'); Flash::error('Fare not found');
return redirect(route('admin.awards.index')); return redirect(route('admin.awards.index'));
} }
$this->awardRepository->delete($id); $this->awardRepository->delete($id);
Flash::success('Award deleted successfully.'); Flash::success('Fare deleted successfully.');
return redirect(route('admin.awards.index')); return redirect(route('admin.awards.index'));
} }
@@ -147,12 +147,6 @@ class FlightController extends Controller
$flights = collect(); $flights = collect();
$saved_flights = []; $saved_flights = [];
foreach ($user->bids as $bid) { foreach ($user->bids as $bid) {
// Remove any invalid bids (flight doesn't exist or something)
if (!$bid->flight) {
$bid->delete();
continue;
}
$flights->add($bid->flight); $flights->add($bid->flight);
$saved_flights[] = $bid->flight->id; $saved_flights[] = $bid->flight->id;
} }
@@ -52,7 +52,7 @@ class ProfileController extends Controller
{ {
// Is the ACARS module enabled? // Is the ACARS module enabled?
$acars_enabled = false; $acars_enabled = false;
$acars = Module::find('VMSAcars'); $acars = Module::find('VMSACARS');
if ($acars) { if ($acars) {
$acars_enabled = $acars->isEnabled(); $acars_enabled = $acars->isEnabled();
} }
@@ -95,7 +95,6 @@ class ProfileController extends Controller
'user' => $user, 'user' => $user,
'userFields' => $userFields, 'userFields' => $userFields,
'airports' => $airports, 'airports' => $airports,
'acars' => $this->acarsEnabled(),
]); ]);
} }
@@ -122,7 +121,7 @@ class ProfileController extends Controller
$airlines = $this->airlineRepo->selectBoxList(); $airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only')); $airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only'));
$userFields = $this->userRepo->getUserFields($user, true); $userFields = $this->userRepo->getUserFields($user, false);
return view('profile.edit', [ return view('profile.edit', [
'user' => $user, 'user' => $user,
@@ -110,12 +110,6 @@ class SimBriefController
$loadmax = $lfactor + $lfactorv; $loadmax = $lfactor + $lfactorv;
$loadmax = $loadmax > 100 ? 100 : $loadmax; $loadmax = $loadmax > 100 ? 100 : $loadmax;
// Failsafe for admins not defining load values for their flights
// and also leave the general settings empty, set loadmax to 100
if ($loadmax === 0) {
$loadmax = 100;
}
// Show the main simbrief form // Show the main simbrief form
return view('flights.simbrief_form', [ return view('flights.simbrief_form', [
'flight' => $flight, 'flight' => $flight,
-1
View File
@@ -27,7 +27,6 @@ class Pirep extends Resource
{ {
$res = parent::toArray($request); $res = parent::toArray($request);
$res['ident'] = $this->ident; $res['ident'] = $this->ident;
$res['phase'] = $this->status;
$res['status_text'] = PirepStatus::label($this->status); $res['status_text'] = PirepStatus::label($this->status);
// Set these to the response units // Set these to the response units
-8
View File
@@ -4,14 +4,6 @@ namespace App\Models;
use App\Contracts\Model; use App\Contracts\Model;
/**
* @property int id
* @property string pirep_id
* @property int fare_id
* @property int count
* @property Pirep pirep
* @property Fare fare
*/
class PirepFare extends Model class PirepFare extends Model
{ {
public $table = 'pirep_fares'; public $table = 'pirep_fares';
+2 -22
View File
@@ -46,32 +46,12 @@ class AirportService extends Service
return; return;
} }
$raw_metar = $this->metarProvider->metar($icao); $raw_metar = $this->metarProvider->get_metar($icao);
if ($raw_metar && $raw_metar !== '') { if ($raw_metar && $raw_metar !== '') {
return new Metar($raw_metar); return new Metar($raw_metar);
} }
} }
/**
* Return the METAR for a given airport
*
* @param $icao
*
* @return Metar|null
*/
public function getTaf($icao)
{
$icao = trim($icao);
if ($icao === '') {
return;
}
$raw_taf = $this->metarProvider->taf($icao);
if ($raw_taf && $raw_taf !== '') {
return new Metar($raw_taf, true);
}
}
/** /**
* Lookup an airport's information from a remote provider. This handles caching * Lookup an airport's information from a remote provider. This handles caching
* the data internally * the data internally
@@ -121,7 +101,7 @@ class AirportService extends Service
} }
// Don't lookup the airport, so just add in something generic // Don't lookup the airport, so just add in something generic
if (!setting('general.auto_airport_lookup')) { if (!setting('general.auto_airport_lookup', false)) {
$airport = new Airport([ $airport = new Airport([
'id' => $icao, 'id' => $icao,
'icao' => $icao, 'icao' => $icao,
+1 -1
View File
@@ -92,6 +92,6 @@ class CronService extends Service
// More than 5 minutes... there's a problem // More than 5 minutes... there's a problem
$diff = $dt_now->diff($dt); $diff = $dt_now->diff($dt);
return $diff->i > 60 * 12; // Hasn't run for 12 hours return $diff->i > 5;
} }
} }
+3 -3
View File
@@ -286,7 +286,9 @@ class FareService extends Service
*/ */
public function getForPirep(Pirep $pirep) public function getForPirep(Pirep $pirep)
{ {
return PirepFare::where('pirep_id', $pirep->id)->get(); $found_fares = PirepFare::where('pirep_id', $pirep->id)->get();
return $found_fares;
} }
/** /**
@@ -311,8 +313,6 @@ class FareService extends Service
$fare['pirep_id'] = $pirep->id; $fare['pirep_id'] = $pirep->id;
// other fields: ['fare_id', 'count'] // other fields: ['fare_id', 'count']
Log::info('Saving fare pirep='.$pirep->id.', fare='.$fare['count']);
$field = new PirepFare($fare); $field = new PirepFare($fare);
$field->save(); $field->save();
} }
-7
View File
@@ -137,13 +137,6 @@ class FlightService extends Service
{ {
/** @var \Illuminate\Support\Collection $subfleets */ /** @var \Illuminate\Support\Collection $subfleets */
$subfleets = $flight->subfleets; $subfleets = $flight->subfleets;
// If no subfleets assigned to a flight get users allowed subfleets
if ($subfleets === null || $subfleets->count() === 0) {
$subfleets = $this->userSvc->getAllowableSubfleets($user);
}
// If subfleets are still empty return the flight
if ($subfleets === null || $subfleets->count() === 0) { if ($subfleets === null || $subfleets->count() === 0) {
return $flight; return $flight;
} }
@@ -51,8 +51,13 @@ class FlightImporter extends ImportExport
'fields' => 'nullable', 'fields' => 'nullable',
]; ];
/** @var AirportService */
private $airportSvc; private $airportSvc;
/** @var FareService */
private $fareSvc; private $fareSvc;
/** @var FlightService */
private $flightSvc; private $flightSvc;
/** /**
+1 -5
View File
@@ -118,11 +118,7 @@ class ImportService extends Service
// turn it into a collection and run some filtering // turn it into a collection and run some filtering
$row = collect($row)->map(function ($val, $index) { $row = collect($row)->map(function ($val, $index) {
$val = trim($val); $val = trim($val);
if ($val === '') { return empty($val) ? null : $val;
return;
}
return $val;
})->toArray(); })->toArray();
// Try to validate // Try to validate
+2 -51
View File
@@ -9,16 +9,13 @@ use Exception;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/** /**
* Return the raw METAR/TAF string from the NOAA Aviation Weather Service * Return the raw METAR string from the NOAA Aviation Weather Service
*/ */
class AviationWeather extends Metar class AviationWeather extends Metar
{ {
private const METAR_URL = private const METAR_URL =
'https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&hoursBeforeNow=3&mostRecent=true&stationString='; 'https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&hoursBeforeNow=3&mostRecent=true&stationString=';
private const TAF_URL =
'https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=tafs&requestType=retrieve&format=xml&hoursBeforeNow=3&mostRecent=true&stationString=';
private $httpClient; private $httpClient;
public function __construct(HttpClient $httpClient) public function __construct(HttpClient $httpClient)
@@ -36,7 +33,7 @@ class AviationWeather extends Metar
* *
* @return string * @return string
*/ */
protected function get_metar($icao): string protected function metar($icao): string
{ {
if ($icao === '') { if ($icao === '') {
return ''; return '';
@@ -70,53 +67,7 @@ class AviationWeather extends Metar
return $xml->data->METAR->raw_text->__toString(); return $xml->data->METAR->raw_text->__toString();
} catch (Exception $e) { } catch (Exception $e) {
Log::error('Error reading METAR: '.$e->getMessage()); Log::error('Error reading METAR: '.$e->getMessage());
return '';
}
}
/**
* Do the actual retrieval of the TAF
*
* @param $icao
*
* @throws \GuzzleHttp\Exception\GuzzleException
*
* @return string
*/
protected function get_taf($icao): string
{
if ($icao === '') {
return '';
}
$tafurl = static::TAF_URL.$icao;
try {
$tafres = $this->httpClient->get($tafurl, []);
$tafxml = simplexml_load_string($tafres);
$tafattrs = $tafxml->data->attributes();
if (!isset($tafattrs['num_results'])) {
return '';
}
$tafnum_results = $tafattrs['num_results'];
if (empty($tafnum_results)) {
return '';
}
$tafnum_results = (int) $tafnum_results;
if ($tafnum_results === 0) {
return '';
}
if (count($tafxml->data->TAF->raw_text) === 0) {
return '';
}
return $tafxml->data->TAF->raw_text->__toString();
} catch (Exception $e) {
Log::error('Error reading TAF: '.$e->getMessage());
return ''; return '';
} }
} }
+1 -37
View File
@@ -21,7 +21,6 @@ use App\Repositories\SubfleetRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Support\Units\Time; use App\Support\Units\Time;
use App\Support\Utils; use App\Support\Utils;
use Carbon\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use function is_array; use function is_array;
@@ -255,41 +254,6 @@ class UserService extends Service
return $user; return $user;
} }
/**
* Return all of the users that are determined to be on leave. Only goes through the
* currently active users. If the user doesn't have a PIREP, then the creation date
* of the user record is used to determine the difference
*/
public function findUsersOnLeave(): array
{
$leave_days = setting('pilots.auto_leave_days');
if ($leave_days === 0) {
return [];
}
$return_users = [];
$date = Carbon::now('UTC');
$users = User::with(['last_pirep'])->where('state', UserState::ACTIVE)->get();
/** @var User $user */
foreach ($users as $user) {
// If they haven't submitted a PIREP, use the date that the user was created
if (!$user->last_pirep) {
$diff_date = $user->created_at;
} else {
$diff_date = $user->last_pirep->submitted_at;
}
// See if the difference is larger than what the setting calls for
if ($date->diffInDays($diff_date) > $leave_days) {
$return_users[] = $user;
}
}
return $return_users;
}
/** /**
* Return the subfleets this user is allowed access to, * Return the subfleets this user is allowed access to,
* based on their current rank * based on their current rank
@@ -462,7 +426,7 @@ class UserService extends Service
$user->state = UserState::ON_LEAVE; $user->state = UserState::ON_LEAVE;
$user->save(); $user->save();
event(new UserStateChanged($user, UserState::ON_LEAVE)); event(new UserStateChanged($user, UserState::ACTIVE));
$user->refresh(); $user->refresh();
return $user; return $user;
-4
View File
@@ -123,10 +123,6 @@ class Utils
return $val; return $val;
} }
if ($result->hostname === 'localhost') {
return 'localhost';
}
// Couldn't validate a domain, see if this is an IP address? // Couldn't validate a domain, see if this is an IP address?
if (filter_var($url, FILTER_VALIDATE_IP)) { if (filter_var($url, FILTER_VALIDATE_IP)) {
return $url; return $url;
+1 -4
View File
@@ -11,8 +11,7 @@ use App\Services\AirportService;
class Weather extends Widget class Weather extends Widget
{ {
protected $config = [ protected $config = [
'icao' => null, 'icao' => null,
'raw_only' => null,
]; ];
/** /**
@@ -23,12 +22,10 @@ class Weather extends Widget
/** @var \App\Services\AirportService $airportSvc */ /** @var \App\Services\AirportService $airportSvc */
$airportSvc = app(AirportService::class); $airportSvc = app(AirportService::class);
$metar = $airportSvc->getMetar($this->config['icao']); $metar = $airportSvc->getMetar($this->config['icao']);
$taf = $airportSvc->getTaf($this->config['icao']);
return view('widgets.weather', [ return view('widgets.weather', [
'config' => $this->config, 'config' => $this->config,
'metar' => $metar, 'metar' => $metar,
'taf' => $taf,
'unit_alt' => setting('units.altitude'), 'unit_alt' => setting('units.altitude'),
'unit_dist' => setting('units.distance'), 'unit_dist' => setting('units.distance'),
'unit_temp' => setting('units.temperature'), 'unit_temp' => setting('units.temperature'),
+1 -2
View File
@@ -58,8 +58,7 @@
"webpatser/laravel-uuid": "~3.0", "webpatser/laravel-uuid": "~3.0",
"oomphinc/composer-installers-extender": "^1.1", "oomphinc/composer-installers-extender": "^1.1",
"laravel/ui": "^2.0", "laravel/ui": "^2.0",
"madnest/madzipper": "^1.0", "madnest/madzipper": "^1.0"
"elcobvg/laravel-opcache": "^0.4.1"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.0", "barryvdh/laravel-debugbar": "^3.0",
Generated
+1 -58
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "5bd282b9602f7922883277e45c82603e", "content-hash": "6f5fb0bd12dc789b1ad1613ddf907a80",
"packages": [ "packages": [
{ {
"name": "akaunting/money", "name": "akaunting/money",
@@ -1655,63 +1655,6 @@
], ],
"time": "2020-08-08T21:28:19+00:00" "time": "2020-08-08T21:28:19+00:00"
}, },
{
"name": "elcobvg/laravel-opcache",
"version": "0.4.1",
"source": {
"type": "git",
"url": "https://github.com/elcobvg/laravel-opcache.git",
"reference": "a9af6d12f8bda562dd187f6d5368c647c1f02a44"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/elcobvg/laravel-opcache/zipball/a9af6d12f8bda562dd187f6d5368c647c1f02a44",
"reference": "a9af6d12f8bda562dd187f6d5368c647c1f02a44",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"mockery/mockery": "1.0",
"orchestra/testbench": "3.5",
"phpunit/phpunit": "6.5",
"squizlabs/php_codesniffer": "3.2"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"ElcoBvg\\Opcache\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"ElcoBvg\\Opcache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Elco Brouwer von Gonzenbach",
"email": "elco.brouwer@gmail.com"
}
],
"description": "Custom OPcache Cache Driver for Laravel. Faster than Redis or memcached.",
"homepage": "https://github.com/elcobvg/laravel-opcache",
"keywords": [
"Opcache",
"cache",
"driver",
"laravel",
"webprofiler"
],
"time": "2020-05-16T00:51:29+00:00"
},
{ {
"name": "facade/flare-client-php", "name": "facade/flare-client-php",
"version": "1.3.5", "version": "1.3.5",
+17 -5
View File
@@ -131,10 +131,22 @@ return [
'Yaml' => Symfony\Component\Yaml\Yaml::class, 'Yaml' => Symfony\Component\Yaml\Yaml::class,
// ENUMS // ENUMS
'ActiveState' => App\Models\Enums\ActiveState::class, 'AcarsType' => App\Models\Enums\AcarsType::class,
'UserState' => App\Models\Enums\UserState::class, 'ActiveState' => App\Models\Enums\ActiveState::class,
'PirepSource' => App\Models\Enums\PirepSource::class, 'AircraftState' => App\Models\Enums\AircraftState::class,
'PirepState' => App\Models\Enums\PirepState::class, 'AircraftStatus' => App\Models\Enums\AircraftStatus::class,
'PirepStatus' => App\Models\Enums\PirepStatus::class, 'Days' => App\Models\Enums\Days::class,
'ExpenseType' => App\Models\Enums\ExpenseType::class,
'FareType' => App\Models\Enums\FareType::class,
'FlightType' => App\Models\Enums\FlightType::class,
'FuelType' => App\Models\Enums\FuelType::class,
'JournalType' => App\Models\Enums\JournalType::class,
'NavaidType' => App\Models\Enums\NavaidType::class,
'PageType' => App\Models\Enums\PageType::class,
'PirepFieldSource' => App\Models\Enums\PirepFieldSource::class,
'PirepSource' => App\Models\Enums\PirepSource::class,
'PirepState' => App\Models\Enums\PirepState::class,
'PirepStatus' => App\Models\Enums\PirepStatus::class,
'UserState' => App\Models\Enums\UserState::class,
], ],
]; ];
+6 -6
View File
@@ -135,7 +135,7 @@ return [
*/ */
'monitor_backups' => [ 'monitor_backups' => [
[ [
'name' => config('app.name'), 'name' => config(config('app.name'), 'phpvms-backup'),
'disks' => ['local'], 'disks' => ['local'],
'health_checks' => [ 'health_checks' => [
MaximumAgeInDays::class => 1, MaximumAgeInDays::class => 1,
@@ -172,27 +172,27 @@ return [
/* /*
* The number of days for which backups must be kept. * The number of days for which backups must be kept.
*/ */
'keep_all_backups_for_days' => 3, 'keep_all_backups_for_days' => 7,
/* /*
* The number of days for which daily backups must be kept. * The number of days for which daily backups must be kept.
*/ */
'keep_daily_backups_for_days' => 2, 'keep_daily_backups_for_days' => 7,
/* /*
* The number of weeks for which one weekly backup must be kept. * The number of weeks for which one weekly backup must be kept.
*/ */
'keep_weekly_backups_for_weeks' => 2, 'keep_weekly_backups_for_weeks' => 4,
/* /*
* The number of months for which one monthly backup must be kept. * The number of months for which one monthly backup must be kept.
*/ */
'keep_monthly_backups_for_months' => 1, 'keep_monthly_backups_for_months' => 4,
/* /*
* The number of years for which one yearly backup must be kept. * The number of years for which one yearly backup must be kept.
*/ */
'keep_yearly_backups_for_years' => 1, 'keep_yearly_backups_for_years' => 2,
/* /*
* After cleaning up the backups remove the oldest backup until * After cleaning up the backups remove the oldest backup until
+2 -6
View File
@@ -9,18 +9,14 @@ return [
'key' => 'airports.lookup:', 'key' => 'airports.lookup:',
'time' => 60 * 30, 'time' => 60 * 30,
], ],
'METAR_WEATHER_LOOKUP' => [ 'WEATHER_LOOKUP' => [
'key' => 'airports.weather.metar.', // append icao 'key' => 'airports.weather.', // append icao
'time' => 60 * 60, // Cache for 60 minutes 'time' => 60 * 60, // Cache for 60 minutes
], ],
'RANKS_PILOT_LIST' => [ 'RANKS_PILOT_LIST' => [
'key' => 'ranks.pilot_list', 'key' => 'ranks.pilot_list',
'time' => 60 * 10, 'time' => 60 * 10,
], ],
'TAF_WEATHER_LOOKUP' => [
'key' => 'airports.weather.taf.', // append icao
'time' => 60 * 60, // Cache for 60 minutes
],
'USER_API_KEY' => [ 'USER_API_KEY' => [
'key' => 'user.apikey', 'key' => 'user.apikey',
'time' => 60 * 5, // 5 min 'time' => 60 * 5, // 5 min
-1
View File
@@ -23,7 +23,6 @@ return [
'tokenizer', 'tokenizer',
'json', 'json',
'curl', 'curl',
'dom',
], ],
// Make sure these are writable // Make sure these are writable
+2 -18
View File
@@ -15,7 +15,8 @@ return [
| |
*/ */
'default' => env('MAIL_DRIVER', 'smtp'), 'driver' => env('MAIL_DRIVER', 'smtp'),
'mailers' => [ 'mailers' => [
'smtp' => [ 'smtp' => [
'transport' => 'smtp', 'transport' => 'smtp',
@@ -70,21 +71,4 @@ return [
'address' => env('MAIL_FROM_ADDRESS', 'no-reply@phpvms.net'), 'address' => env('MAIL_FROM_ADDRESS', 'no-reply@phpvms.net'),
], ],
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
*/
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
]; ];
+1 -1
View File
@@ -20,7 +20,7 @@ return [
'expire_on_close' => false, 'expire_on_close' => false,
'encrypt' => false, 'encrypt' => false,
'files' => storage_path('framework/sessions'), 'files' => storage_path('framework/sessions'),
'connection' => 'mysql', 'connection' => null,
'table' => 'sessions', 'table' => 'sessions',
'store' => null, 'store' => null,
'lottery' => [1, 100], 'lottery' => [1, 100],
+1 -1
View File
@@ -42,7 +42,7 @@ class PilotHoursAwards extends Award
*/ */
public function check($flight_minutes = null): bool public function check($flight_minutes = null): bool
{ {
if (!is_numeric($flight_minutes)) { if (!is_int($flight_minutes)) {
Log::error('PilotHourAwards: Flight time "'.$flight_minutes.'" is not a valid flight time'); Log::error('PilotHourAwards: Flight time "'.$flight_minutes.'" is not a valid flight time');
return false; return false;
} }
+8 -3
View File
@@ -1983,6 +1983,11 @@
"resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.4.1.tgz", "resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.4.1.tgz",
"integrity": "sha512-p5rxsK/IyEDQm2CwiHxxUi0MZZtvVFbhWmyMOt4lLkA4bujDA1TGoKT0i1FKIWiugAdP+kK8T5KMDFIKQCLYIA==" "integrity": "sha512-p5rxsK/IyEDQm2CwiHxxUi0MZZtvVFbhWmyMOt4lLkA4bujDA1TGoKT0i1FKIWiugAdP+kK8T5KMDFIKQCLYIA=="
}, },
"bootstrap3": {
"version": "npm:bootstrap@3.4.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz",
"integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA=="
},
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -5812,9 +5817,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
}, },
"lodash.memoize": { "lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
+1 -1
View File
@@ -33,7 +33,7 @@
"leaflet-providers": "1.0.*", "leaflet-providers": "1.0.*",
"leaflet-rotatedmarker": "^0.2.0", "leaflet-rotatedmarker": "^0.2.0",
"leaflet.geodesic": "^2.5.2", "leaflet.geodesic": "^2.5.2",
"lodash": ">=4.17.21", "lodash": ">=4.17.19",
"marked": "^1.2.2", "marked": "^1.2.2",
"minimist": "^1.2.2", "minimist": "^1.2.2",
"moment": "^2.29.1", "moment": "^2.29.1",
-8
View File
@@ -130,11 +130,3 @@
border-radius: 5px; border-radius: 5px;
width: 250px; width: 250px;
} }
/*
* fix the dropdown menu on mobile view
*/
.dropdown-menu:not(.show) {
display: none;
}
+2 -3
View File
@@ -80,7 +80,7 @@ return [
// Overrides config/mail.php // Overrides config/mail.php
'mail' => [ 'mail' => [
'default' => 'mail', # Default is to use the mail() fn 'driver' => 'mail', # Default is to use the mail() fn
'mailers' => [ 'mailers' => [
'smtp' => [ 'smtp' => [
'transport' => 'smtp', 'transport' => 'smtp',
@@ -107,8 +107,7 @@ return [
// Overrides config/session.php // Overrides config/session.php
'session' => [ 'session' => [
'driver' => 'database', 'default' => 'file',
'connection' => 'mysql',
'lifetime' => 60 * 24, # 24 hours 'lifetime' => 60 * 24, # 24 hours
], ],
]; ];
@@ -4,7 +4,7 @@
<div class="content"> <div class="content">
@if($cron_problem_exists) @if($cron_problem_exists)
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
The cron has not run in more than 12 hours; make sure it's setup and check logs at There was a problem running the cron; make sure it's setup and check logs at
<span class="text-monospace bg-gradient-dark">storage/logs/cron.log</span>. <span class="text-monospace bg-gradient-dark">storage/logs/cron.log</span>.
<a href="{{ docs_link('cron') }}" target="_blank">See the docs</a> <a href="{{ docs_link('cron') }}" target="_blank">See the docs</a>
</div> </div>
@@ -223,8 +223,8 @@
<form action="https://my.vatsim.net/pilots/flightplan" method="GET" target="_blank"> <form action="https://my.vatsim.net/pilots/flightplan" method="GET" target="_blank">
<input type="hidden" name="raw" value="{{ $simbrief->xml->atc->flightplan_text }}"> <input type="hidden" name="raw" value="{{ $simbrief->xml->atc->flightplan_text }}">
<input type="hidden" name="fuel_time" value="@secstohhmm($simbrief->xml->times->endurance)"> <input type="hidden" name="fuel_time" value="@secstohhmm($simbrief->xml->times->endurance)">
<input type="hidden" name="speed" value="@if(substr($simbrief->xml->atc->initial_spd,0,1) === '0') {{ substr($simbrief->xml->atc->initial_spd,1) }} @else {{ $simbrief->xml->atc->initial_spd }} @endif"> <input type="hidden" name="speed" value="{{ $simbrief->xml->atc->initial_spd }}">
<input type="hidden" name="altitude" value="{{ $simbrief->xml->general->initial_altitude }}"> <input type="hidden" name="altitude" value="{{ $simbrief->xml->atc->initial_alt }}">
<input id="vatsim_prefile" type="submit" class="btn btn-primary" value="File ATC on VATSIM"/> <input id="vatsim_prefile" type="submit" class="btn btn-primary" value="File ATC on VATSIM"/>
</form> </form>
</div> </div>
@@ -133,11 +133,11 @@
<div class="text-right"> <div class="text-right">
@if (isset($acars) && $acars === true) @if (isset($acars) && $acars === true)
<a href="{{ route('frontend.profile.acars') }}" class="btn btn-primary" <a href="{{ route('frontend.profile.acars') }}" class="btn btn-primary"
onclick="alert('Copy or Save to \'My Documents/phpVMS\'')">ACARS Config</a> onclick="alert('Save to \'My Documents/phpVMS\'')">ACARS Config</a>
&nbsp; &nbsp;
@endif @endif
<a href="{{ route('frontend.profile.regen_apikey') }}" class="btn btn-warning" <a href="{{ route('frontend.profile.regen_apikey') }}" class="btn btn-warning"
onclick="return confirm('Are you sure? This will reset your API key!')">@lang('profile.newapikey')</a> onclick="return confirm({{ __('Are you sure? This will reset your API key.') }})">@lang('profile.newapikey')</a>
&nbsp; &nbsp;
<a href="{{ route('frontend.profile.edit', [$user->id]) }}" <a href="{{ route('frontend.profile.edit', [$user->id]) }}"
class="btn btn-primary">@lang('common.edit')</a> class="btn btn-primary">@lang('common.edit')</a>
@@ -171,7 +171,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<table class="table table-full-width"> <table class="table table-full-width">
@foreach($userFields as $field) @foreach($userFields as $field)
@if(!$field->private) @if($field->public === true)
<tr> <tr>
<td>{{ $field->name }}</td> <td>{{ $field->name }}</td>
<td>{{ $field->value }}</td> <td>{{ $field->value }}</td>
@@ -4,8 +4,10 @@ If you want to edit this, you can reference the CheckWX API docs:
https://api.checkwx.com/#metar-decoded https://api.checkwx.com/#metar-decoded
--}} --}}
<table class="table table-striped"> @if(!$metar)
@if($config['raw_only'] != true && $metar) <p>@lang('widgets.weather.nometar')</p>
@else
<table class="table table-striped">
<tr> <tr>
<td>@lang('widgets.weather.conditions')</td> <td>@lang('widgets.weather.conditions')</td>
<td>{{ $metar['category'] }}</td> <td>{{ $metar['category'] }}</td>
@@ -18,35 +20,35 @@ https://api.checkwx.com/#metar-decoded
</td> </td>
</tr> </tr>
@if($metar['visibility']) @if($metar['visibility'])
<tr> <tr>
<td>Visibility</td> <td>Visibility</td>
<td>{{ $metar['visibility'][$unit_dist] }} {{$unit_dist}}</td> <td>{{ $metar['visibility'][$unit_dist] }} {{$unit_dist}}</td>
</tr> </tr>
@endif @endif
@if($metar['runways_visual_range']) @if($metar['runways_visual_range'])
<tr> <tr>
<td>Runway Visual Range</td> <td>Runway Visual Range</td>
<td> <td>
@foreach($metar['runways_visual_range'] as $rvr) @foreach($metar['runways_visual_range'] as $rvr)
<b>RWY{{ $rvr['runway'] }}</b>; {{ $rvr['report'] }}<br> <b>RWY{{ $rvr['runway'] }}</b>; {{ $rvr['report'] }}<br>
@endforeach @endforeach
</td> </td>
</tr> </tr>
@endif @endif
@if($metar['present_weather_report'] <> 'Dry') @if($metar['present_weather_report'] <> 'Dry')
<tr> <tr>
<td>Phenomena</td> <td>Phenomena</td>
<td>{{ $metar['present_weather_report'] }}</td> <td>{{ $metar['present_weather_report'] }}</td>
</tr> </tr>
@endif @endif
@if($metar['clouds'] || $metar['cavok']) @if($metar['clouds'] || $metar['cavok'])
<tr> <tr>
<td>@lang('widgets.weather.clouds')</td> <td>@lang('widgets.weather.clouds')</td>
<td> <td>
@if($unit_alt === 'ft') {{ $metar['clouds_report_ft'] }} @else {{ $metar['clouds_report'] }} @endif @if($unit_alt === 'ft') {{ $metar['clouds_report_ft'] }} @else {{ $metar['clouds_report'] }} @endif
@if($metar['cavok'] == 1) Ceiling and Visibility OK @endif @if($metar['cavok'] == 1) Ceiling and Visibility OK @endif
</td> </td>
</tr> </tr>
@endif @endif
<tr> <tr>
<td>Temperature</td> <td>Temperature</td>
@@ -61,20 +63,20 @@ https://api.checkwx.com/#metar-decoded
<td>{{ number_format($metar['barometer']['hPa']) }} hPa / {{ number_format($metar['barometer']['inHg'], 2) }} inHg</td> <td>{{ number_format($metar['barometer']['hPa']) }} hPa / {{ number_format($metar['barometer']['inHg'], 2) }} inHg</td>
</tr> </tr>
@if($metar['recent_weather_report']) @if($metar['recent_weather_report'])
<tr> <tr>
<td>Recent Phenomena</td> <td>Recent Phenomena</td>
<td>{{ $metar['recent_weather_report'] }}</td> <td>{{ $metar['recent_weather_report'] }}</td>
</tr> </tr>
@endif @endif
@if($metar['runways_report']) @if($metar['runways_report'])
<tr> <tr>
<td>Runway Condition</td> <td>Runway Condition</td>
<td> <td>
@foreach($metar['runways_report'] as $runway) @foreach($metar['runways_report'] as $runway)
<b>RWY{{ $runway['runway'] }}</b>; {{ $runway['report'] }}<br> <b>RWY{{ $runway['runway'] }}</b>; {{ $runway['report'] }}<br>
@endforeach @endforeach
</td> </td>
</tr> </tr>
@endif @endif
@if($metar['remarks']) @if($metar['remarks'])
<tr> <tr>
@@ -86,13 +88,9 @@ https://api.checkwx.com/#metar-decoded
<td>@lang('widgets.weather.updated')</td> <td>@lang('widgets.weather.updated')</td>
<td>{{$metar['observed_time']}} ({{$metar['observed_age']}})</td> <td>{{$metar['observed_time']}} ({{$metar['observed_age']}})</td>
</tr> </tr>
@endif
<tr> <tr>
<td>@lang('common.metar')</td> <td>@lang('common.metar')</td>
<td>@if($metar) {{ $metar['raw'] }} @else @lang('widgets.weather.nometar') @endif</td> <td>{{ $metar['raw'] }}</td>
</tr> </tr>
<tr> </table>
<td>TAF</td> @endif
<td>@if($taf) {{ $taf['raw'] }} @else @lang('widgets.weather.nometar') @endif</td>
</tr>
</table>
+20 -2
View File
@@ -467,6 +467,11 @@ class ImporterTest extends TestCase
*/ */
public function testFlightImporter(): void public function testFlightImporter(): void
{ {
$this->updateSetting('general.auto_airport_lookup', false);
factory(Airport::class)->create(['icao' => 'KAUS']);
factory(Airport::class)->create(['icao' => 'KJFK']);
[$airline, $subfleet] = $this->insertFlightsScaffoldData(); [$airline, $subfleet] = $this->insertFlightsScaffoldData();
$file_path = base_path('tests/data/flights.csv'); $file_path = base_path('tests/data/flights.csv');
@@ -531,6 +536,19 @@ class ImporterTest extends TestCase
// Check the subfleets // Check the subfleets
$subfleets = $flight->subfleets; $subfleets = $flight->subfleets;
$this->assertCount(1, $subfleets); $this->assertCount(1, $subfleets);
// Reimport, see that data updates
$file_path = base_path('tests/data/flights-update.csv');
$status = $this->importSvc->importFlights($file_path);
$flight = Flight::where([
'airline_id' => $airline->id,
'flight_number' => '1972',
])->first();
$this->assertCount(1, $status['success']);
$this->assertEquals('12:00 CST', $flight->dpt_time);
$this->assertEquals('18:35 EST', $flight->arr_time);
} }
/** /**
@@ -634,8 +652,8 @@ class ImporterTest extends TestCase
$this->assertEquals(true, $airport->hub); $this->assertEquals(true, $airport->hub);
$this->assertEquals('30.1945', $airport->lat); $this->assertEquals('30.1945', $airport->lat);
$this->assertEquals('-97.6699', $airport->lon); $this->assertEquals('-97.6699', $airport->lon);
$this->assertEquals(0.0, $airport->ground_handling_cost); $this->assertEquals(250, $airport->ground_handling_cost);
$this->assertEquals(setting('airports.default_jet_a_fuel_cost'), $airport->fuel_jeta_cost); $this->assertEquals(0.8, $airport->fuel_jeta_cost); // should be updated
// See if it imported // See if it imported
$airport = Airport::where([ $airport = Airport::where([
-2
View File
@@ -168,8 +168,6 @@ class MetarTest extends TestCase
public function testHttpCallSuccess() public function testHttpCallSuccess()
{ {
$this->mockXmlResponse('aviationweather/kjfk.xml'); $this->mockXmlResponse('aviationweather/kjfk.xml');
/** @var AirportService $airportSvc */
$airportSvc = app(AirportService::class); $airportSvc = app(AirportService::class);
$this->assertInstanceOf(Metar::class, $airportSvc->getMetar('kjfk')); $this->assertInstanceOf(Metar::class, $airportSvc->getMetar('kjfk'));
+10 -15
View File
@@ -3,9 +3,7 @@
namespace Tests; namespace Tests;
use App\Models\Aircraft; use App\Models\Aircraft;
use App\Models\Enums\UserState;
use App\Models\Flight; use App\Models\Flight;
use App\Models\Pirep;
use App\Models\Subfleet; use App\Models\Subfleet;
use App\Models\User; use App\Models\User;
use Exception; use Exception;
@@ -23,37 +21,34 @@ trait TestData
{ {
$subfleet = $this->createSubfleetWithAircraft(1); $subfleet = $this->createSubfleetWithAircraft(1);
$rank = $this->createRank(2, [$subfleet['subfleet']->id]); $rank = $this->createRank(2, [$subfleet['subfleet']->id]);
$user = factory(User::class)->create(array_merge([
return factory(User::class)->create(array_merge([
'flight_time' => 1000, 'flight_time' => 1000,
'rank_id' => $rank->id, 'rank_id' => $rank->id,
'state' => UserState::ACTIVE,
], $attrs)); ], $attrs));
return $user;
} }
/** /**
* Create a new PIREP with a proper subfleet/rank/user and an * Create a new PIREP with a proper subfleet/rank/user and an
* aircraft that the user is allowed to fly * aircraft that the user is allowed to fly
* *
* @param array $user_attrs Additional attributes for the user
* @param array $pirep_attrs Additional attributes for the PIREP
*
* @throws \Exception
*
* @return \App\Models\Pirep * @return \App\Models\Pirep
*/ */
protected function createPirep(array $user_attrs = [], array $pirep_attrs = []) protected function createPirep()
{ {
$subfleet = $this->createSubfleetWithAircraft(2); $subfleet = $this->createSubfleetWithAircraft(2);
$rank = $this->createRank(10, [$subfleet['subfleet']->id]); $rank = $this->createRank(10, [$subfleet['subfleet']->id]);
$this->user = factory(\App\Models\User::class)->create(array_merge([ $this->user = factory(\App\Models\User::class)->create([
'rank_id' => $rank->id, 'rank_id' => $rank->id,
], $user_attrs)); ]);
// Return a Pirep model // Return a Pirep model
return factory(Pirep::class)->make(array_merge([ $pirep = factory(\App\Models\Pirep::class)->make([
'aircraft_id' => $subfleet['aircraft']->random()->id, 'aircraft_id' => $subfleet['aircraft']->random()->id,
], $pirep_attrs)); ]);
return $pirep;
} }
/** /**
-47
View File
@@ -5,14 +5,11 @@ namespace Tests;
use App\Exceptions\PilotIdNotFound; use App\Exceptions\PilotIdNotFound;
use App\Exceptions\UserPilotIdExists; use App\Exceptions\UserPilotIdExists;
use App\Models\Airline; use App\Models\Airline;
use App\Models\Enums\UserState;
use App\Models\Fare; use App\Models\Fare;
use App\Models\Pirep;
use App\Models\User; use App\Models\User;
use App\Repositories\SettingRepository; use App\Repositories\SettingRepository;
use App\Services\FareService; use App\Services\FareService;
use App\Services\UserService; use App\Services\UserService;
use Carbon\Carbon;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
class UserTest extends TestCase class UserTest extends TestCase
@@ -327,48 +324,4 @@ class UserTest extends TestCase
$this->assertEquals($expected, $user->name_private); $this->assertEquals($expected, $user->name_private);
} }
} }
/**
* @throws \Exception
*/
public function testUserLeave(): void
{
$this->createUser(['status' => UserState::ACTIVE]);
$users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(0, count($users_on_leave));
$this->updateSetting('pilots.auto_leave_days', 1);
$user = $this->createUser([
'status' => UserState::ACTIVE,
'created_at' => Carbon::now('UTC')->subDays(5),
]);
$users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(1, count($users_on_leave));
$this->assertEquals($user->id, $users_on_leave[0]->id);
// Give that user a new PIREP, still old
/** @var \App\Models\Pirep $pirep */
$pirep = factory(Pirep::class)->create(['submitted_at' => Carbon::now('UTC')->subDays(5)]);
$user->last_pirep_id = $pirep->id;
$user->save();
$user->refresh();
$users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(1, count($users_on_leave));
$this->assertEquals($user->id, $users_on_leave[0]->id);
// Create a new PIREP
/** @var \App\Models\Pirep $pirep */
$pirep = factory(Pirep::class)->create(['submitted_at' => Carbon::now('UTC')]);
$user->last_pirep_id = $pirep->id;
$user->save();
$user->refresh();
$users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(0, count($users_on_leave));
}
} }
-1
View File
@@ -100,6 +100,5 @@ class UtilsTest extends TestCase
$this->assertEquals('phpvms.co.uk', Utils::getRootDomain('http://phpvms.co.uk')); $this->assertEquals('phpvms.co.uk', Utils::getRootDomain('http://phpvms.co.uk'));
$this->assertEquals('phpvms.co.uk', Utils::getRootDomain('http://www.phpvms.co.uk')); $this->assertEquals('phpvms.co.uk', Utils::getRootDomain('http://www.phpvms.co.uk'));
$this->assertEquals('127.0.0.1', Utils::getRootDomain('http://127.0.0.1')); $this->assertEquals('127.0.0.1', Utils::getRootDomain('http://127.0.0.1'));
$this->assertEquals('localhost', Utils::getRootDomain('http://localhost'));
} }
} }
+4 -4
View File
@@ -1,4 +1,4 @@
icao,iata,name,location,country,timezone,hub,lat,lon,ground_handling_cost,fuel_100ll_cost,fuel_jeta_cost,fuel_mogas_cost icao,iata,name,location,country,timezone,hub,lat,lon,ground_handling_cost,fuel_100ll_cost,fuel_jeta_cost,fuel_mogas_cost
KAUS,AUS,Austin-Bergstrom,"Austin, Texas, USA", United States,America/Chicago,1,30.1945,-97.6699,0,,, KAUS,AUS,Austin-Bergstrom,"Austin, Texas, USA", United States,America/Chicago,1,30.1945,-97.6699,250,0.8,0.8,0.8
KSFO,SFO,San Francisco,"San Francisco, California, USA", United States,America/California,1,30.1945,-97.6699,,,0.9, KSFO,SFO,San Francisco,"San Francisco, California, USA", United States,America/California,1,30.1945,-97.6699,,,0.9,
KJFK,JFK,Kennedy,"Queens, New York, USA", United States,America/New_York,0,30.1945,abcd,150,,0.8, KJFK,JFK,Kennedy,"Queens, New York, USA", United States,America/New_York,0,30.1945,abcd,150,,0.8,
1 icao iata name location country timezone hub lat lon ground_handling_cost fuel_100ll_cost fuel_jeta_cost fuel_mogas_cost
2 KAUS AUS Austin-Bergstrom Austin, Texas, USA United States America/Chicago 1 30.1945 -97.6699 0 250 0.8 0.8 0.8
3 KSFO SFO San Francisco San Francisco, California, USA United States America/California 1 30.1945 -97.6699 0.9
4 KJFK JFK Kennedy Queens, New York, USA United States America/New_York 0 30.1945 abcd 150 0.8
+2
View File
@@ -0,0 +1,2 @@
airline,flight_number,route_code,route_leg,dpt_airport,arr_airport,alt_airport,days,dpt_time,arr_time,level,distance,flight_time,flight_type,load_factor, load_factor_variance,pilot_pay,route,notes,active,subfleets,fares,fields
VMS,1972, ,,KAUS,KJFK,KLGA,15,12:00 CST,18:35 EST,350,1477,207,J,85,0,100, ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6,"Just a flight",1,A32X,Y?price=300&cost=100&capacity=130;F?price=600&cost=400;B?,Departure Gate=4;Arrival Gate=C41
1 airline flight_number route_code route_leg dpt_airport arr_airport alt_airport days dpt_time arr_time level distance flight_time flight_type load_factor load_factor_variance pilot_pay route notes active subfleets fares fields
2 VMS 1972 KAUS KJFK KLGA 15 12:00 CST 18:35 EST 350 1477 207 J 85 0 100 ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6 Just a flight 1 A32X Y?price=300&cost=100&capacity=130;F?price=600&cost=400;B? Departure Gate=4;Arrival Gate=C41