Add acars map page and show in-progress flights
This commit is contained in:
@@ -2,16 +2,15 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
use App\Facades\Utils;
|
||||
|
||||
class AcarsReplay extends Command
|
||||
{
|
||||
protected $signature = 'phpvms:replay {files} {--manual} {--write-all}';
|
||||
protected $signature = 'phpvms:replay {files} {--manual} {--write-all} {--no-submit}';
|
||||
protected $description = 'Replay an ACARS file';
|
||||
|
||||
/**
|
||||
@@ -64,11 +63,13 @@ class AcarsReplay extends Command
|
||||
$pft = Utils::hoursToMinutes($flight->planned_hrsenroute,
|
||||
$flight->planned_minenroute);
|
||||
|
||||
$flight_number = substr($flight->callsign, 3);
|
||||
|
||||
$response = $this->httpClient->post('/api/pirep/prefile', [
|
||||
'json' => [
|
||||
'airline_id' => 1,
|
||||
'flight_number' => '6028',
|
||||
'aircraft_id' => 1, # TODO: Lookup
|
||||
'flight_number' => $flight_number,
|
||||
'aircraft_id' => 1,
|
||||
'dpt_airport_id' => $flight->planned_depairport,
|
||||
'arr_airport_id' => $flight->planned_destairport,
|
||||
'altitude' => $flight->planned_altitude,
|
||||
@@ -84,6 +85,7 @@ class AcarsReplay extends Command
|
||||
/**
|
||||
* Mark the PIREP as filed
|
||||
* @param $pirep_id
|
||||
* @return mixed
|
||||
*/
|
||||
protected function filePirep($pirep_id)
|
||||
{
|
||||
@@ -187,8 +189,8 @@ class AcarsReplay extends Command
|
||||
|
||||
$this->postUpdate($pirep_id, $update);
|
||||
|
||||
# we're done
|
||||
if($updates->count() === 0) {
|
||||
# we're done and don't put the "no-submit" option
|
||||
if($updates->count() === 0 && !$this->option('no-submit')) {
|
||||
$this->filePirep($pirep_id);
|
||||
}
|
||||
})->filter(function ($updates, $idx) {
|
||||
|
||||
@@ -56,13 +56,6 @@ class CreatePirepTables extends Migration
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('pirep_events', function(Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('pirep_id', 12);
|
||||
$table->string('event', 64);
|
||||
$table->dateTime('dt');
|
||||
});
|
||||
|
||||
/*
|
||||
* Financial tables/fields
|
||||
*/
|
||||
|
||||
@@ -3,41 +3,40 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Log;
|
||||
use App\Models\Acars;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\AppBaseController;
|
||||
|
||||
use App\Models\Acars;
|
||||
use App\Services\GeoService;
|
||||
use App\Repositories\AcarsRepository;
|
||||
use App\Repositories\PirepRepository;
|
||||
|
||||
use App\Http\Resources\Acars as AcarsResource;
|
||||
|
||||
|
||||
class AcarsController extends AppBaseController
|
||||
{
|
||||
protected $acarsRepo, $pirepRepo;
|
||||
protected $acarsRepo, $geoSvc, $pirepRepo;
|
||||
|
||||
public function __construct(
|
||||
GeoService $geoSvc,
|
||||
AcarsRepository $acarsRepo,
|
||||
PirepRepository $pirepRepo
|
||||
) {
|
||||
$this->geoSvc = $geoSvc;
|
||||
$this->acarsRepo = $acarsRepo;
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the flights (as points) in GeoJSON format
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/*PirepResource::withoutWrapping();
|
||||
return new PirepResource($this->pirepRepo->find($id));*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current ACARS map data in GeoJSON format
|
||||
* @param Request $request
|
||||
*/
|
||||
public function geojson(Request $request)
|
||||
{
|
||||
$pireps = $this->acarsRepo->getPositions();
|
||||
$positions = $this->geoSvc->getFeatureForLiveFlights($pireps);
|
||||
|
||||
return response(json_encode($positions), 200, [
|
||||
'Content-type' => 'application/json'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -181,4 +181,13 @@ class PirepController extends AppBaseController
|
||||
AcarsResource::withoutWrapping();
|
||||
return new AcarsResource($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param Request $request
|
||||
*/
|
||||
public function geojson($id, Request $request)
|
||||
{
|
||||
$pirep = $this->pirepRepo->find($id);
|
||||
}
|
||||
}
|
||||
|
||||
37
app/Http/Controllers/Frontend/AcarsController.php
Normal file
37
app/Http/Controllers/Frontend/AcarsController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Frontend;
|
||||
|
||||
use App\Models\Pirep;
|
||||
use App\Repositories\AcarsRepository;
|
||||
use App\Services\GeoService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AcarsController extends Controller
|
||||
{
|
||||
private $acarsRepo, $geoSvc;
|
||||
|
||||
public function __construct(
|
||||
AcarsRepository $acarsRepo,
|
||||
GeoService $geoSvc
|
||||
) {
|
||||
$this->acarsRepo = $acarsRepo;
|
||||
$this->geoSvc = $geoSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$pireps = $this->acarsRepo->getPositions();
|
||||
$positions = $this->geoSvc->getFeatureForLiveFlights($pireps);
|
||||
|
||||
return $this->view('acars.index',[
|
||||
'pireps' => $pireps,
|
||||
'positions' => $positions,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,8 @@ class Pirep extends BaseModel
|
||||
|
||||
public function acars()
|
||||
{
|
||||
return $this->hasMany('App\Models\Acars', 'pirep_id');
|
||||
return $this->hasMany('App\Models\Acars', 'pirep_id')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
public function aircraft()
|
||||
@@ -118,12 +119,8 @@ class Pirep extends BaseModel
|
||||
|
||||
public function comments()
|
||||
{
|
||||
return $this->hasMany('App\Models\PirepComment', 'pirep_id');
|
||||
}
|
||||
|
||||
public function events()
|
||||
{
|
||||
return $this->hasMany('App\Models\PirepEvent', 'pirep_id');
|
||||
return $this->hasMany('App\Models\PirepComment', 'pirep_id')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
public function fields()
|
||||
@@ -141,14 +138,17 @@ class Pirep extends BaseModel
|
||||
return $this->user();
|
||||
}
|
||||
|
||||
public function route()
|
||||
/**
|
||||
* Relationship that holds the current position, but limits the ACARS
|
||||
* relationship to only one row (the latest), to prevent an N+! problem
|
||||
*/
|
||||
public function position()
|
||||
{
|
||||
return [];
|
||||
return $this->hasOne('App\Models\Acars', 'pirep_id')->latest();
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\Models\User', 'user_id');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
/**
|
||||
* Class PirepEvent
|
||||
*
|
||||
* @package App\Models
|
||||
*/
|
||||
class PirepEvent extends BaseModel
|
||||
{
|
||||
public $table = 'pirep_fields';
|
||||
|
||||
public $fillable
|
||||
= [
|
||||
'name',
|
||||
'value',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts
|
||||
= [
|
||||
'name' => 'string',
|
||||
'required' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $rules
|
||||
= [
|
||||
'name' => 'required',
|
||||
];
|
||||
|
||||
public function pirep()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Pirep', 'pirep_id');
|
||||
}
|
||||
}
|
||||
@@ -66,10 +66,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
protected function mapApiRoutes()
|
||||
{
|
||||
Route::group([
|
||||
'middleware' => [
|
||||
'api',
|
||||
'api.auth',
|
||||
],
|
||||
'middleware' => ['api'],
|
||||
'namespace' => $this->namespace."\\Api",
|
||||
'prefix' => 'api',
|
||||
'as' => 'api.',
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\Acars;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\Enums\PirepState;
|
||||
use App\Models\Enums\PirepStatus;
|
||||
|
||||
use App\Repositories\Traits\CacheableRepository;
|
||||
use Prettus\Repository\Contracts\CacheableInterface;
|
||||
|
||||
class AcarsRepository extends BaseRepository implements CacheableInterface
|
||||
class AcarsRepository extends BaseRepository //implements CacheableInterface
|
||||
{
|
||||
use CacheableRepository;
|
||||
//use CacheableRepository;
|
||||
|
||||
public function model()
|
||||
{
|
||||
@@ -19,4 +23,30 @@ class AcarsRepository extends BaseRepository implements CacheableInterface
|
||||
{
|
||||
return $this->findWhere(['pirep_id' => $pirep_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the PIREPS that are in-progress, and then
|
||||
* get the latest update for those flights
|
||||
* @return Pirep
|
||||
*/
|
||||
public function getPositions()
|
||||
{
|
||||
return Pirep::with(['airline', 'position'])
|
||||
->where(['state' => PirepState::IN_PROGRESS])
|
||||
->get();
|
||||
|
||||
/*return Pirep::with(['acars' => function($q) {
|
||||
return $q->limit(1);
|
||||
}])->where(['state' => PirepState::IN_PROGRESS])->get();*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function getAllAcarsPoints()
|
||||
{
|
||||
return Pirep::with('acars')->where([
|
||||
'state' => PirepState::IN_PROGRESS
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register API routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| is assigned the "api" middleware group. Enjoy building your API!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::group([], function ()
|
||||
/**
|
||||
* public routes
|
||||
*/
|
||||
Route::group([], function()
|
||||
{
|
||||
Route::match(['get'], 'status', 'BaseController@status');
|
||||
|
||||
Route::match(['get'], 'airports/{id}', 'AirportController@get');
|
||||
Route::match(['get'], 'airports/{id}/lookup', 'AirportController@lookup');
|
||||
Route::match(['get'], 'acars', 'AcarsController@index');
|
||||
|
||||
Route::match(['get'], 'flights/search', 'FlightController@search');
|
||||
Route::match(['get'], 'flights/{id}', 'FlightController@get');
|
||||
|
||||
Route::match(['post'], 'pirep/{id}/geojson', 'PirepController@file');
|
||||
|
||||
Route::match(['get'], 'status', 'BaseController@status');
|
||||
});
|
||||
|
||||
/**
|
||||
* these need to be authenticated with a user's API key
|
||||
*/
|
||||
Route::group(['middleware' => ['api.auth']], function ()
|
||||
{
|
||||
Route::match(['get'], 'airports/{id}', 'AirportController@get');
|
||||
Route::match(['get'], 'airports/{id}/lookup', 'AirportController@lookup');
|
||||
|
||||
Route::match(['get'], 'pirep/{id}', 'PirepController@get');
|
||||
Route::match(['post'], 'pirep/prefile', 'PirepController@prefile');
|
||||
Route::match(['post'], 'pirep/{id}/file', 'PirepController@file');
|
||||
@@ -30,9 +30,6 @@ Route::group([], function ()
|
||||
Route::match(['get'], 'pirep/{id}/acars', 'PirepController@acars_get');
|
||||
Route::match(['post'], 'pirep/{id}/acars', 'PirepController@acars_store');
|
||||
|
||||
Route::match(['get'], 'acars', 'AcarsController@index');
|
||||
Route::match(['get'], 'acars/geojson', 'AcarsController@geojson');
|
||||
|
||||
# This is the info of the user whose token is in use
|
||||
Route::match(['get'], 'user', 'UserController@index');
|
||||
#Route::match(['get'], 'user/bids', 'UserController@index');
|
||||
|
||||
@@ -8,8 +8,10 @@ Route::get('/', 'HomeController@index')->name('home');
|
||||
Route::group([
|
||||
'namespace' => 'Frontend', 'prefix' => '', 'as' => 'frontend.'
|
||||
], function() {
|
||||
Route::get('/r/{id}', 'PirepController@show')->name('pirep.show.public');
|
||||
Route::get('/p/{id}', 'ProfileController@show')->name('profile.show.public');
|
||||
Route::get('r/{id}', 'PirepController@show')->name('pirep.show.public');
|
||||
Route::get('p/{id}', 'ProfileController@show')->name('profile.show.public');
|
||||
|
||||
Route::get('livemap', 'AcarsController@index')->name('livemap.public');
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -22,7 +24,7 @@ Route::group([
|
||||
Route::resource('dashboard', 'DashboardController');
|
||||
|
||||
Route::get('flights/search', 'FlightController@search')->name('flights.search');
|
||||
Route::match(['post'], '/flights/save', 'FlightController@save')->name('flights.save');
|
||||
Route::post('flights/save', 'FlightController@save')->name('flights.save');
|
||||
Route::resource('flights', 'FlightController');
|
||||
|
||||
Route::resource('profile', 'ProfileController');
|
||||
|
||||
@@ -139,6 +139,32 @@ class GeoService extends BaseService
|
||||
return $coords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the center point between two sets of coordinates
|
||||
* @param $latA
|
||||
* @param $lonA
|
||||
* @param $latB
|
||||
* @param $lonB
|
||||
* @return array
|
||||
* @throws \League\Geotools\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function getCenter($latA, $lonA, $latB, $lonB)
|
||||
{
|
||||
$geotools = new Geotools();
|
||||
$coordA = new Coordinate([$latA, $lonA]);
|
||||
$coordB = new Coordinate([$latB, $lonB]);
|
||||
|
||||
$vertex = $geotools->vertex()->setFrom($coordA)->setTo($coordB);
|
||||
$middlePoint = $vertex->middle();
|
||||
|
||||
$center = [
|
||||
$middlePoint->getLatitude(),
|
||||
$middlePoint->getLongitude()
|
||||
];
|
||||
|
||||
return $center;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an array/relationship of ACARS model points
|
||||
* @param Pirep $pirep
|
||||
@@ -171,12 +197,42 @@ class GeoService extends BaseService
|
||||
# Convert to a feature
|
||||
$route_line = new Feature(new LineString($route_line), [], 1);
|
||||
|
||||
# TODO: Draw the plane icon from the last point
|
||||
|
||||
return [
|
||||
'line' => new FeatureCollection([$route_line]),
|
||||
'points' => new FeatureCollection($route_points)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single feature point for the
|
||||
*/
|
||||
public function getFeatureForLiveFlights($pireps)
|
||||
{
|
||||
$flight_points = [];
|
||||
|
||||
/**
|
||||
* @var Pirep $pirep
|
||||
*/
|
||||
foreach($pireps as $pirep) {
|
||||
|
||||
/**
|
||||
* @var $point \App\Models\Acars
|
||||
*/
|
||||
$point = $pirep->position;
|
||||
$flight_points[] = new Feature(
|
||||
new Point([$point->lon, $point->lat]), [
|
||||
'gs' => $point->gs,
|
||||
'alt' => $point->altitude,
|
||||
'heading' => $point->heading ?: 0,
|
||||
'popup' => 'Flight: ' . $pirep->ident,
|
||||
]);
|
||||
}
|
||||
|
||||
return new FeatureCollection($flight_points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a FeatureCollection GeoJSON object
|
||||
* @param Flight $flight
|
||||
@@ -300,30 +356,4 @@ class GeoService extends BaseService
|
||||
'actual_route_points' => $actual_route['points'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the center point between two sets of coordinates
|
||||
* @param $latA
|
||||
* @param $lonA
|
||||
* @param $latB
|
||||
* @param $lonB
|
||||
* @return array
|
||||
* @throws \League\Geotools\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function getCenter($latA, $lonA, $latB, $lonB)
|
||||
{
|
||||
$geotools = new Geotools();
|
||||
$coordA = new Coordinate([$latA, $lonA]);
|
||||
$coordB = new Coordinate([$latB, $lonB]);
|
||||
|
||||
$vertex = $geotools->vertex()->setFrom($coordA)->setTo($coordB);
|
||||
$middlePoint = $vertex->middle();
|
||||
|
||||
$center = [
|
||||
$middlePoint->getLatitude(),
|
||||
$middlePoint->getLongitude()
|
||||
];
|
||||
|
||||
return $center;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user