Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions app/Aircraft.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;

class Aircraft {

public static $data;
private static $initialized = false;
const FILENAME = 'private/aircraft.json';

public static function init() {
if (self::$initialized) {
return 1;
}
if (Storage::disk('local')->exists(self::FILENAME)) {
self::$data = Collection::fromJson(Storage::disk('local')->get(self::FILENAME));
}
}
Comment on lines +14 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to set $initialized to true here? Or is that built into Laravel to do automatically?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not aware of a cleaner way to do this. Please let me know if you have a good trick.


public static function fetch($acid) {
$ac = self::$data->where('ac_type', $acid)->first();
return (is_null($ac)) ? null : (object) $ac;
}
}
Aircraft::init();
149 changes: 149 additions & 0 deletions app/Console/Commands/UpdateFAA.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

namespace App\Console\Commands;

use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Console\Helper\ProgressIndicator;
use Symfony\Component\Console\Output\ConsoleOutput;

class UpdateFAA extends Command {
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'FAA:update-faa';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Updates FAA-specific datafiles';

const FAA_DATA_URL = 'https://www.fly.faa.gov/rmt/data_file/';
private $routes = [
[
'name' => 'PRD',
'model' => 'App\PreferredRoute',
'file' => 'prefroutes_db.csv'
]
];
private ProgressIndicator $progressIndicator;
private $path;

/**
* Execute the console command.
*/
public function handle() {
$this->info('Updating FAA-specific datafiles');
$this->path = Storage::disk('local')->path('private/');
$this->setup_progress_indicator();
$this->update_routes();
}

private function update_routes(): void {
foreach ($this->routes as $route) {
$route = (object) $route;
$this->progressIndicator->start("Fetching $route->name info from FAA server...");
$this->call_api(SELF::FAA_DATA_URL . $route->file, $this->path, strtolower($route->name) . '_new.csv');
$this->progressIndicator->finish("Fetching $route->name info from FAA server... done");

// Update table
$this->progressIndicator->start("Updating $route->name table...");
if (($handle = fopen($this->path . strtolower($route->name) . '_new.csv', "r")) !== false) {
$route->model::truncate();
while (($rte_line = fgetcsv($handle, null, ",")) !== false) {
if (!is_array($rte_line)) {
continue;
}
$bom = "\xef\xbb\xbf";
if (substr($rte_line[0], 0, 3) === $bom) {
$rte_line[0] = substr($rte_line[0], 3);
}
if ($rte_line[0] == 'RCode' || $rte_line[0] == 'Orig') { // It's the header line, skip it
continue;
}
if ($route->name == 'CDR') {
$load_arr = [
'route_code' => $rte_line[0],
'origin' => $rte_line[1],
'destination' => $rte_line[2],
'departure_fix' => substr($rte_line[3], 0, 5), // Enforce 5 characters
'route_string' => $rte_line[4],
'departure_center' => $rte_line[5],
'arrival_center' => $rte_line[6],
'transit_centers' => $rte_line[7],
'coordination_required' => $rte_line[8],
'play' => $rte_line[9],
'navigation_equipment' => $rte_line[10]
];
} else {
$load_arr = [
'orig' => $rte_line[0],
'route_string' => $rte_line[1],
'dest' => $rte_line[2],
'hours1' => $rte_line[3],
'hours2' => $rte_line[4],
'hours3' => $rte_line[5],
'type' => $rte_line[6],
'area' => $rte_line[7],
'altitude' => (is_numeric($rte_line[8])) ? $rte_line[8] : null,
'aircraft' => $rte_line[9],
'direction' => $rte_line[10],
'seq' => $rte_line[11],
'dcntr' => $rte_line[12],
'acntr' => $rte_line[13]
];
}
$route->model::create($load_arr);
$this->progressIndicator->advance();
}
fclose($handle);
}
$this->progressIndicator->finish("Updating $route->name table... done");

// Remove, rename file
$this->info("Removing unused local $route->name files");
if (file_exists($this->path . $route->name . '.csv')) {
unlink($this->path . $route->name . '.csv');
$this->info("- Deleted $route->name.csv");
}
if (file_exists($this->path . $route->name . '_new.csv')) {
rename($this->path . $route->name . '_new.csv', $this->path . $route->name . '.csv');
}
$this->info("$route->name file cleanup complete");
}
}

private function call_api($url, $path = null, $write_file = null): string|null {
$progress = $this->progressIndicator;
$write_to_filename = (is_null($write_file)) ? basename($url) : $write_file;
$client = new Client();
$response = $client->get($url, [
'config' => [
'curl' => [
'CURLOPT_RETURNTRANSFER' => true,
'CURLOPT_CONNECTTIMEOUT' => 3,
'CURLOPT_ENCODING' => 'gzip',
'CURLOPT_SSL_VERIFYPEER' => false
]
],
'progress' => function () use ($progress) {
$progress->advance();
},
'sink' => $path . $write_to_filename
]);
if ($response->getStatusCode() == 200) {
return $response->getBody();
}
return null;
}

private function setup_progress_indicator(): void {
$output = new ConsoleOutput;
$this->progressIndicator = new ProgressIndicator($output);
}
}
2 changes: 2 additions & 0 deletions app/Exports/RealopsExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function headings(): array {
'Point of Arrival',
'Arrival Time',
'Gate',
'Aircraft Type',
'Pilot Name',
'Pilot CID',
'Pilot Email'
Expand All @@ -44,6 +45,7 @@ public function map($flight): array {
$flight->arr_airport,
$flight->est_time_enroute,
$flight->gate,
$flight->aircraft_type,
$pilot->full_name,
$flight->assigned_pilot_id,
$pilot->email
Expand Down
10 changes: 5 additions & 5 deletions app/Http/Controllers/RealopsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ class RealopsController extends Controller {
public function index(Request $request) {
$airport_filter = $request->get('airport_filter');
$flightno_filter = $request->get('flightno_filter');
$actype_filter = $request->get('actype_filter');
$date_filter = $request->get('date_filter');
$time_filter = $request->get('time_filter');

$flights = RealopsFlight::where('flight_number', 'like', '%' . $flightno_filter . '%')
->orWhere('callsign', 'like', '%' . $flightno_filter . '%')
->orWhere('aircraft_type', 'like', '%' . $actype_filter . '%')
->when(! is_null($time_filter), function ($query) use ($time_filter) {
$times = $this->timeBetween($time_filter, 15, 45);
$query->whereTime('dep_time', ">=", Carbon::parse($times[0]))
Expand All @@ -38,7 +40,7 @@ public function index(Request $request) {
->orderBy('dep_time', 'ASC')
->paginate(20);

return view('site.realops')->with('flights', $flights)->with('airport_filter', $airport_filter)->with('flightno_filter', $flightno_filter)->with('date_filter', $date_filter)->with('time_filter', $time_filter);
return view('site.realops', compact('flights', 'airport_filter', 'flightno_filter', 'actype_filter', 'date_filter', 'time_filter'));
}

public function bid($id) {
Expand Down Expand Up @@ -148,6 +150,7 @@ public function createFlight(Request $request) {
$flight->arr_airport = $request->input('arr_airport');
$flight->est_time_enroute = $request->input('est_time_enroute');
$flight->gate = $request->input('gate');
$flight->aircraft_type = $request->input('aircraft_type');
$flight->save();

return redirect('/dashboard/admin/realops')->with('success', 'That flight was created successfully');
Expand Down Expand Up @@ -187,6 +190,7 @@ public function editFlight(Request $request, $id) {
$flight->arr_airport = $request->input('arr_airport');
$flight->est_time_enroute = $request->input('est_time_enroute');
$flight->gate = $request->input('gate');
$flight->aircraft_type = $request->input('aircraft_type');
$flight->save();

$pilot = $flight->assigned_pilot;
Expand All @@ -204,17 +208,13 @@ public function bulkUploadFlights(Request $request) {
]);

try {
// what is this for?
// this doesn't do anything
//$contents = file_get_contents($request->file('file')->getRealPath());
Excel::import(new RealopsFlightImporter, request()->file('file'));
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
$failures = $e->failures();

$errors = "";

foreach ($failures as $failure) {
// L21#0 Blah blah blah (value: 'fbalsdhj')
Log::info($failure);
$errors = $errors.' L'.$failure->row().'#'.$failure->attribute().': '.join(',', $failure->errors()).' ('.$failure->values()[$failure->attribute()].')';
}
Expand Down
6 changes: 6 additions & 0 deletions app/Importers/RealopsFlightImporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function model($row) {
}
$est_time_enroute = null;
$gate = null;
$aircraft_type = null;

if (count($row) > 6) {
$est_time_enroute = $row[6];
Expand All @@ -26,6 +27,10 @@ public function model($row) {
$gate = $row[7];
}

if (count($row) > 8) {
$aircraft_type = $row[8];
}

$flight = new RealopsFlight;
$flight->flight_number = $row[0];
$flight->callsign = $row[1];
Expand All @@ -35,6 +40,7 @@ public function model($row) {
$flight->arr_airport = $row[5];
$flight->est_time_enroute = $est_time_enroute;
$flight->gate = $gate;
$flight->aircraft_type = $aircraft_type;

return $flight;
}
Expand Down
35 changes: 35 additions & 0 deletions app/PreferredRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class PreferredRoute extends Model {
protected $table = 'prd_route';
protected $guarded = [];

public static function routeLookup(string $departure, string $arrival, string $ac_type = 'jets'): string {
$routes = PreferredRoute::where('orig', substr($departure, 1))->where('dest', substr($arrival, 1))->where(function ($query) use ($ac_type) {
$query->where('aircraft', 'LIKE', '%' . strtoupper($ac_type) . '%')->orWhere('aircraft', '');
})->first();
if (!$routes) {
return '';
}
$clean_route = self::remove_origin_destination_points($routes->route_string, $departure, $arrival);
return $clean_route;
}

private static function remove_origin_destination_points($route_string, $departure, $arrival): string {
$route = explode(' ', $route_string);
if (!is_array($route)) {
return '';
}
if ($route[0] == substr($departure, 1)) {
unset($route[0]);
}
if (end($route) == substr($arrival, 1)) {
array_pop($route);
}
return implode(' ', $route);
}
}
Loading