* SimBrief integration #405 * Add briefing as API response; add acars_xml field #405
This commit is contained in:
@@ -130,7 +130,11 @@ class FlightService extends Service
|
||||
*/
|
||||
public function filterSubfleets($user, $flight)
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection $subfleets */
|
||||
$subfleets = $flight->subfleets;
|
||||
if ($subfleets === null || $subfleets->count() === 0) {
|
||||
return $flight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only allow aircraft that the user has access to in their rank
|
||||
|
||||
@@ -8,9 +8,13 @@ use App\Events\PirepCancelled;
|
||||
use App\Events\PirepFiled;
|
||||
use App\Events\PirepRejected;
|
||||
use App\Events\UserStatsChanged;
|
||||
use App\Exceptions\AircraftNotAtAirport;
|
||||
use App\Exceptions\AircraftPermissionDenied;
|
||||
use App\Exceptions\PirepCancelNotAllowed;
|
||||
use App\Exceptions\UserNotAtAirport;
|
||||
use App\Models\Acars;
|
||||
use App\Models\Enums\AcarsType;
|
||||
use App\Models\Enums\FlightType;
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Enums\PirepState;
|
||||
use App\Models\Enums\PirepStatus;
|
||||
@@ -27,24 +31,84 @@ use Illuminate\Support\Facades\Log;
|
||||
class PirepService extends Service
|
||||
{
|
||||
private $geoSvc;
|
||||
private $pilotSvc;
|
||||
private $userSvc;
|
||||
private $pirepRepo;
|
||||
|
||||
/**
|
||||
* @param GeoService $geoSvc
|
||||
* @param PirepRepository $pirepRepo
|
||||
* @param UserService $pilotSvc
|
||||
* @param UserService $userSvc
|
||||
*/
|
||||
public function __construct(
|
||||
GeoService $geoSvc,
|
||||
PirepRepository $pirepRepo,
|
||||
UserService $pilotSvc
|
||||
UserService $userSvc
|
||||
) {
|
||||
$this->geoSvc = $geoSvc;
|
||||
$this->pilotSvc = $pilotSvc;
|
||||
$this->userSvc = $userSvc;
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a prefiled PIREP
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param array $attrs
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return \App\Models\Pirep
|
||||
*/
|
||||
public function prefile(User $user, array $attrs): Pirep
|
||||
{
|
||||
$attrs['user_id'] = $user->id;
|
||||
$attrs['state'] = PirepState::IN_PROGRESS;
|
||||
|
||||
if (!array_key_exists('status', $attrs)) {
|
||||
$attrs['status'] = PirepStatus::INITIATED;
|
||||
}
|
||||
|
||||
// Default to a scheduled passenger flight
|
||||
if (!array_key_exists('flight_type', $attrs)) {
|
||||
$attrs['flight_type'] = FlightType::SCHED_PAX;
|
||||
}
|
||||
|
||||
$pirep = new Pirep($attrs);
|
||||
|
||||
// See if this user is at the current airport
|
||||
/* @noinspection NotOptimalIfConditionsInspection */
|
||||
if (setting('pilots.only_flights_from_current')
|
||||
&& $user->curr_airport_id !== $pirep->dpt_airport_id) {
|
||||
throw new UserNotAtAirport($user, $pirep->dpt_airport);
|
||||
}
|
||||
|
||||
// See if this user is allowed to fly this aircraft
|
||||
if (setting('pireps.restrict_aircraft_to_rank', false)
|
||||
&& !$this->userSvc->aircraftAllowed($user, $pirep->aircraft_id)) {
|
||||
throw new AircraftPermissionDenied($user, $pirep->aircraft);
|
||||
}
|
||||
|
||||
// See if this aircraft is at the departure airport
|
||||
/* @noinspection NotOptimalIfConditionsInspection */
|
||||
if (setting('pireps.only_aircraft_at_dpt_airport')
|
||||
&& $pirep->aircraft_id !== $pirep->dpt_airport_id) {
|
||||
throw new AircraftNotAtAirport($pirep->aircraft);
|
||||
}
|
||||
|
||||
// Find if there's a duplicate, if so, let's work on that
|
||||
$dupe_pirep = $this->findDuplicate($pirep);
|
||||
if ($dupe_pirep !== false) {
|
||||
$pirep = $dupe_pirep;
|
||||
if ($pirep->cancelled) {
|
||||
throw new \App\Exceptions\PirepCancelled($pirep);
|
||||
}
|
||||
}
|
||||
|
||||
$pirep->save();
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PIREP with some given fields
|
||||
*
|
||||
@@ -348,9 +412,9 @@ class PirepService extends Service
|
||||
$ft = $pirep->flight_time;
|
||||
$pilot = $pirep->user;
|
||||
|
||||
$this->pilotSvc->adjustFlightTime($pilot, $ft);
|
||||
$this->pilotSvc->adjustFlightCount($pilot, +1);
|
||||
$this->pilotSvc->calculatePilotRank($pilot);
|
||||
$this->userSvc->adjustFlightTime($pilot, $ft);
|
||||
$this->userSvc->adjustFlightCount($pilot, +1);
|
||||
$this->userSvc->calculatePilotRank($pilot);
|
||||
$pirep->user->refresh();
|
||||
|
||||
// Change the status
|
||||
@@ -387,9 +451,9 @@ class PirepService extends Service
|
||||
$user = $pirep->user;
|
||||
$ft = $pirep->flight_time * -1;
|
||||
|
||||
$this->pilotSvc->adjustFlightTime($user, $ft);
|
||||
$this->pilotSvc->adjustFlightCount($user, -1);
|
||||
$this->pilotSvc->calculatePilotRank($user);
|
||||
$this->userSvc->adjustFlightTime($user, $ft);
|
||||
$this->userSvc->adjustFlightCount($user, -1);
|
||||
$this->userSvc->calculatePilotRank($user);
|
||||
$pirep->user->refresh();
|
||||
}
|
||||
|
||||
|
||||
155
app/Services/SimBriefService.php
Normal file
155
app/Services/SimBriefService.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Contracts\Service;
|
||||
use App\Models\Acars;
|
||||
use App\Models\Enums\AcarsType;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\SimBrief;
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SimBriefService extends Service
|
||||
{
|
||||
private $httpClient;
|
||||
|
||||
public function __construct(GuzzleClient $httpClient)
|
||||
{
|
||||
$this->httpClient = $httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the OFP exists server-side. If it does, download it and
|
||||
* cache it immediately
|
||||
*
|
||||
* @param string $user_id User who generated this
|
||||
* @param string $ofp_id The SimBrief OFP ID
|
||||
* @param string $flight_id The flight ID
|
||||
*
|
||||
* @return SimBrief|null
|
||||
*/
|
||||
public function checkForOfp(string $user_id, string $ofp_id, string $flight_id): SimBrief
|
||||
{
|
||||
$uri = str_replace('{id}', $ofp_id, config('phpvms.simbrief_url'));
|
||||
|
||||
$opts = [
|
||||
'connect_timeout' => 2, // wait two seconds by default
|
||||
'allow_redirects' => false,
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $uri, $opts);
|
||||
if ($response->getStatusCode() !== 200) {
|
||||
return null;
|
||||
}
|
||||
} catch (GuzzleException $e) {
|
||||
Log::error('Simbrief HTTP Error: '.$e->getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
$body = $response->getBody()->getContents();
|
||||
|
||||
$attrs = [
|
||||
'user_id' => $user_id,
|
||||
'flight_id' => $flight_id,
|
||||
'ofp_xml' => $body,
|
||||
];
|
||||
|
||||
// TODO: Retrieve the ACARS XML and store that. For now, replace the doctype
|
||||
|
||||
$new_doctype = '<VMSAcars Type="FlightPlan" version="1.0" generated="'.time().'">';
|
||||
$acars_xml = str_replace('<OFP>', $new_doctype, $body);
|
||||
$acars_xml = str_replace('</OFP>', '</VMSAcars>', $acars_xml);
|
||||
$acars_xml = str_replace("\n", '', $acars_xml);
|
||||
|
||||
$attrs['acars_xml'] = simplexml_load_string($acars_xml)->asXML();
|
||||
|
||||
// Save this into the Simbrief table, if it doesn't already exist
|
||||
return SimBrief::updateOrCreate(
|
||||
['id' => $ofp_id],
|
||||
$attrs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a prefiled PIREP from a given brief.
|
||||
*
|
||||
* 1. Read from the XML the basic PIREP info (dep, arr), and then associate the PIREP
|
||||
* to the flight ID
|
||||
* 2. Remove the flight ID from the SimBrief field and assign the pirep_id to the row
|
||||
* 3. Update the planned flight route in the acars table
|
||||
* 4. Add additional flight fields (ones which match ACARS)
|
||||
*
|
||||
* @param $pirep
|
||||
* @param SimBrief $simBrief The briefing to create the PIREP from
|
||||
*
|
||||
* @return \App\Models\Pirep
|
||||
*/
|
||||
public function attachSimbriefToPirep($pirep, SimBrief $simBrief): Pirep
|
||||
{
|
||||
$this->addRouteToPirep($pirep, $simBrief);
|
||||
|
||||
$simBrief->pirep_id = $pirep->id;
|
||||
$simBrief->flight_id = null;
|
||||
$simBrief->save();
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the route from a SimBrief flight plan to a PIREP
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
* @param SimBrief $simBrief
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
protected function addRouteToPirep($pirep, SimBrief $simBrief): Pirep
|
||||
{
|
||||
// Clear previous entries
|
||||
Acars::where(['pirep_id' => $pirep->id, 'type' => AcarsType::ROUTE])->delete();
|
||||
|
||||
// Create the flight route
|
||||
$order = 1;
|
||||
foreach ($simBrief->xml->getRoute() as $fix) {
|
||||
$position = [
|
||||
'name' => $fix->ident,
|
||||
'pirep_id' => $pirep->id,
|
||||
'type' => AcarsType::ROUTE,
|
||||
'order' => $order++,
|
||||
'lat' => $fix->pos_lat,
|
||||
'lon' => $fix->pos_long,
|
||||
];
|
||||
|
||||
$acars = new Acars($position);
|
||||
$acars->save();
|
||||
}
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any expired entries from the SimBrief table. Expired means there's
|
||||
* a flight_id attached to it, but no pirep_id (meaning it was never used for
|
||||
* an actual flight)
|
||||
*/
|
||||
public function removeExpiredEntries(): void
|
||||
{
|
||||
$expire_days = setting('simbrief.expire_days', 5);
|
||||
$expire_time = Carbon::now('UTC')->subDays($expire_days)->toDateTimeString();
|
||||
|
||||
$briefs = SimBrief::where([
|
||||
['pirep_id', '=', ''],
|
||||
['created_at', '<', $expire_time],
|
||||
])->get();
|
||||
|
||||
foreach ($briefs as $brief) {
|
||||
$brief->delete();
|
||||
|
||||
// TODO: Delete any assets
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user