2017-06-10 14:50:00 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Services;
|
|
|
|
|
2018-01-02 03:48:02 +08:00
|
|
|
use Log;
|
2018-01-03 03:17:22 +08:00
|
|
|
use Carbon\Carbon;
|
|
|
|
use App\Repositories\AcarsRepository;
|
|
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
2018-01-02 03:48:02 +08:00
|
|
|
|
|
|
|
use App\Models\Acars;
|
|
|
|
use App\Models\Navdata;
|
2017-07-02 10:06:55 +08:00
|
|
|
use App\Models\Pirep;
|
|
|
|
use App\Models\PirepFieldValues;
|
2018-01-02 03:48:02 +08:00
|
|
|
use App\Models\User;
|
|
|
|
|
|
|
|
use App\Models\Enums\AcarsType;
|
|
|
|
use App\Models\Enums\PirepSource;
|
|
|
|
use App\Models\Enums\PirepState;
|
2017-07-02 10:06:55 +08:00
|
|
|
|
2017-12-03 00:55:17 +08:00
|
|
|
use App\Events\PirepAccepted;
|
|
|
|
use App\Events\PirepFiled;
|
|
|
|
use App\Events\PirepRejected;
|
2017-12-23 06:32:21 +08:00
|
|
|
use App\Events\UserStatsChanged;
|
2017-06-10 14:50:00 +08:00
|
|
|
|
2018-01-02 03:48:02 +08:00
|
|
|
use App\Repositories\NavdataRepository;
|
2017-12-03 14:48:33 +08:00
|
|
|
use App\Repositories\PirepRepository;
|
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
class PIREPService extends BaseService
|
|
|
|
{
|
2018-01-02 06:01:01 +08:00
|
|
|
protected $acarsRepo,
|
|
|
|
$geoSvc,
|
|
|
|
$navRepo,
|
|
|
|
$pilotSvc,
|
|
|
|
$pirepRepo;
|
2017-06-10 14:50:00 +08:00
|
|
|
|
|
|
|
/**
|
2017-12-03 14:48:33 +08:00
|
|
|
* PIREPService constructor.
|
2018-01-07 23:19:46 +08:00
|
|
|
* @param AcarsRepository $acarsRepo
|
2018-01-02 03:48:02 +08:00
|
|
|
* @param GeoService $geoSvc
|
|
|
|
* @param NavdataRepository $navRepo
|
2017-12-03 14:48:33 +08:00
|
|
|
* @param PirepRepository $pirepRepo
|
2018-01-07 23:19:46 +08:00
|
|
|
* @param UserService $pilotSvc
|
2017-06-10 14:50:00 +08:00
|
|
|
*/
|
2017-12-03 14:48:33 +08:00
|
|
|
public function __construct(
|
2018-01-02 06:01:01 +08:00
|
|
|
AcarsRepository $acarsRepo,
|
2018-01-02 03:48:02 +08:00
|
|
|
GeoService $geoSvc,
|
|
|
|
NavdataRepository $navRepo,
|
2018-01-02 06:01:01 +08:00
|
|
|
PirepRepository $pirepRepo,
|
|
|
|
UserService $pilotSvc
|
|
|
|
)
|
|
|
|
{
|
|
|
|
$this->acarsRepo = $acarsRepo;
|
2018-01-02 03:48:02 +08:00
|
|
|
$this->geoSvc = $geoSvc;
|
2017-12-03 14:48:33 +08:00
|
|
|
$this->pilotSvc = $pilotSvc;
|
2018-01-02 03:48:02 +08:00
|
|
|
$this->navRepo = $navRepo;
|
2017-12-03 14:48:33 +08:00
|
|
|
$this->pirepRepo = $pirepRepo;
|
2017-06-10 14:50:00 +08:00
|
|
|
}
|
|
|
|
|
2018-01-03 03:17:22 +08:00
|
|
|
/**
|
|
|
|
* Find if there are duplicates to a given PIREP. Ideally, the passed
|
|
|
|
* in PIREP hasn't been saved or gone through the create() method
|
|
|
|
* @param Pirep $pirep
|
|
|
|
* @return bool|Pirep
|
|
|
|
*/
|
|
|
|
public function findDuplicate(Pirep $pirep)
|
|
|
|
{
|
|
|
|
$minutes = setting('pireps.duplicate_check_time', 10);
|
|
|
|
$time_limit = Carbon::now()->subMinutes($minutes)->toDateTimeString();
|
|
|
|
|
|
|
|
$where = [
|
|
|
|
'user_id' => $pirep->user_id,
|
|
|
|
'airline_id' => $pirep->airline_id,
|
|
|
|
'flight_number' => $pirep->flight_number,
|
|
|
|
];
|
|
|
|
|
2018-01-24 05:48:30 +08:00
|
|
|
if(filled($pirep->route_code)) {
|
2018-01-03 03:17:22 +08:00
|
|
|
$where['route_code'] = $pirep->route_code;
|
|
|
|
}
|
|
|
|
|
2018-01-24 05:48:30 +08:00
|
|
|
if(filled($pirep->route_leg)) {
|
2018-01-03 03:17:22 +08:00
|
|
|
$where['route_leg'] = $pirep->route_leg;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$found_pireps = Pirep::where($where)
|
|
|
|
->where('created_at', '>=', $time_limit)
|
|
|
|
->get();
|
|
|
|
|
|
|
|
if($found_pireps->count() === 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $found_pireps[0];
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-02 03:48:02 +08:00
|
|
|
/**
|
|
|
|
* Save the route into the ACARS table with AcarsType::ROUTE
|
|
|
|
* @param Pirep $pirep
|
|
|
|
* @return Pirep
|
|
|
|
*/
|
|
|
|
public function saveRoute(Pirep $pirep): Pirep
|
|
|
|
{
|
|
|
|
# Delete all the existing nav points
|
|
|
|
Acars::where([
|
2018-01-02 23:40:42 +08:00
|
|
|
'pirep_id' => $pirep->id,
|
|
|
|
'type' => AcarsType::ROUTE,
|
|
|
|
])->delete();
|
2018-01-02 03:48:02 +08:00
|
|
|
|
|
|
|
# Delete the route
|
2018-01-02 06:01:01 +08:00
|
|
|
if (empty($pirep->route)) {
|
2018-01-02 03:48:02 +08:00
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
2018-01-06 04:33:22 +08:00
|
|
|
if(!$pirep->dpt_airport) {
|
|
|
|
Log::error('saveRoute: dpt_airport not found: '.$pirep->dpt_airport_id);
|
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
2018-01-02 05:04:32 +08:00
|
|
|
$route = $this->geoSvc->getCoordsFromRoute(
|
|
|
|
$pirep->dpt_airport_id,
|
|
|
|
$pirep->arr_airport_id,
|
|
|
|
[$pirep->dpt_airport->lat, $pirep->dpt_airport->lon],
|
|
|
|
$pirep->route
|
2018-01-02 03:48:02 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var $point Navdata
|
|
|
|
*/
|
2018-01-02 23:40:42 +08:00
|
|
|
$point_count = 1;
|
2018-01-02 06:01:01 +08:00
|
|
|
foreach ($route as $point) {
|
2018-01-02 03:48:02 +08:00
|
|
|
$acars = new Acars();
|
|
|
|
$acars->pirep_id = $pirep->id;
|
|
|
|
$acars->type = AcarsType::ROUTE;
|
|
|
|
$acars->nav_type = $point->type;
|
2018-01-02 23:40:42 +08:00
|
|
|
$acars->order = $point_count;
|
2018-01-02 03:48:02 +08:00
|
|
|
$acars->name = $point->id;
|
|
|
|
$acars->lat = $point->lat;
|
|
|
|
$acars->lon = $point->lon;
|
|
|
|
|
|
|
|
$acars->save();
|
2018-01-02 23:40:42 +08:00
|
|
|
++$point_count;
|
2018-01-02 03:48:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
/**
|
|
|
|
* Create a new PIREP with some given fields
|
|
|
|
*
|
|
|
|
* @param Pirep $pirep
|
|
|
|
* @param array [PirepFieldValues] $field_values
|
|
|
|
*
|
|
|
|
* @return Pirep
|
|
|
|
*/
|
2018-01-02 06:01:01 +08:00
|
|
|
public function create(Pirep $pirep, array $field_values = []): Pirep
|
2017-12-03 14:48:33 +08:00
|
|
|
{
|
2018-01-02 06:01:01 +08:00
|
|
|
if (empty($field_values)) {
|
2017-08-24 03:19:05 +08:00
|
|
|
$field_values = [];
|
|
|
|
}
|
2017-07-02 10:06:55 +08:00
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
# Figure out what default state should be. Look at the default
|
|
|
|
# behavior from the rank that the pilot is assigned to
|
2017-12-26 05:19:34 +08:00
|
|
|
$default_state = PirepState::PENDING;
|
2018-01-02 06:01:01 +08:00
|
|
|
if ($pirep->source === PirepSource::ACARS) {
|
|
|
|
if ($pirep->pilot->rank->auto_approve_acars) {
|
2017-12-26 05:19:34 +08:00
|
|
|
$default_state = PirepState::ACCEPTED;
|
|
|
|
}
|
2017-07-04 14:05:37 +08:00
|
|
|
} else {
|
2018-01-02 06:01:01 +08:00
|
|
|
if ($pirep->pilot->rank->auto_approve_manual) {
|
2017-12-26 05:19:34 +08:00
|
|
|
$default_state = PirepState::ACCEPTED;
|
|
|
|
}
|
2017-07-04 14:05:37 +08:00
|
|
|
}
|
2017-07-02 10:06:55 +08:00
|
|
|
|
2017-08-24 03:19:05 +08:00
|
|
|
$pirep->save();
|
|
|
|
$pirep->refresh();
|
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
foreach ($field_values as $fv) {
|
2017-07-02 10:06:55 +08:00
|
|
|
$v = new PirepFieldValues();
|
2017-08-24 03:19:05 +08:00
|
|
|
$v->pirep_id = $pirep->id;
|
2017-07-02 10:06:55 +08:00
|
|
|
$v->name = $fv['name'];
|
|
|
|
$v->value = $fv['value'];
|
|
|
|
$v->source = $fv['source'];
|
|
|
|
$v->save();
|
|
|
|
}
|
2017-06-10 14:50:00 +08:00
|
|
|
|
2017-12-03 14:48:33 +08:00
|
|
|
Log::info('New PIREP filed', [$pirep]);
|
2017-12-03 00:55:17 +08:00
|
|
|
event(new PirepFiled($pirep));
|
|
|
|
|
2017-08-24 03:19:05 +08:00
|
|
|
# only update the pilot last state if they are accepted
|
2017-12-20 10:19:36 +08:00
|
|
|
if ($default_state === PirepState::ACCEPTED) {
|
2017-12-26 05:19:34 +08:00
|
|
|
$pirep = $this->accept($pirep);
|
|
|
|
$this->setPilotState($pirep->pilot, $pirep);
|
2017-08-24 03:19:05 +08:00
|
|
|
}
|
2017-07-04 14:05:37 +08:00
|
|
|
|
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
2017-12-03 14:48:33 +08:00
|
|
|
/**
|
|
|
|
* @param Pirep $pirep
|
2017-12-20 10:19:36 +08:00
|
|
|
* @param int $new_state
|
2017-12-03 14:48:33 +08:00
|
|
|
* @return Pirep
|
|
|
|
*/
|
2017-12-20 10:19:36 +08:00
|
|
|
public function changeState(Pirep $pirep, int $new_state)
|
2017-07-04 14:05:37 +08:00
|
|
|
{
|
2018-01-02 06:01:01 +08:00
|
|
|
Log::info('PIREP ' . $pirep->id . ' state change from ' . $pirep->state . ' to ' . $new_state);
|
2017-12-03 14:48:33 +08:00
|
|
|
|
2017-12-20 10:19:36 +08:00
|
|
|
if ($pirep->state === $new_state) {
|
2017-07-04 14:05:37 +08:00
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Move from a PENDING status into either ACCEPTED or REJECTED
|
|
|
|
*/
|
2017-12-20 10:19:36 +08:00
|
|
|
if ($pirep->state === PirepState::PENDING) {
|
|
|
|
if ($new_state === PirepState::ACCEPTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
return $this->accept($pirep);
|
2017-12-20 10:19:36 +08:00
|
|
|
} elseif ($new_state === PirepState::REJECTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
return $this->reject($pirep);
|
|
|
|
} else {
|
|
|
|
return $pirep;
|
|
|
|
}
|
2018-01-02 06:01:01 +08:00
|
|
|
} /*
|
2017-07-04 14:05:37 +08:00
|
|
|
* Move from a ACCEPTED to REJECTED status
|
|
|
|
*/
|
2017-12-20 10:19:36 +08:00
|
|
|
elseif ($pirep->state === PirepState::ACCEPTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
$pirep = $this->reject($pirep);
|
|
|
|
return $pirep;
|
2018-01-02 06:01:01 +08:00
|
|
|
} /**
|
2017-07-04 14:05:37 +08:00
|
|
|
* Move from REJECTED to ACCEPTED
|
|
|
|
*/
|
2017-12-20 10:19:36 +08:00
|
|
|
elseif ($pirep->state === PirepState::REJECTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
$pirep = $this->accept($pirep);
|
|
|
|
return $pirep;
|
|
|
|
}
|
2017-12-20 10:19:36 +08:00
|
|
|
|
|
|
|
return $pirep->refresh();
|
2017-07-04 14:05:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Pirep $pirep
|
|
|
|
* @return Pirep
|
|
|
|
*/
|
2017-12-14 00:56:26 +08:00
|
|
|
public function accept(Pirep $pirep): Pirep
|
2017-07-04 14:05:37 +08:00
|
|
|
{
|
|
|
|
# moving from a REJECTED state to ACCEPTED, reconcile statuses
|
2017-12-20 10:19:36 +08:00
|
|
|
if ($pirep->state === PirepState::ACCEPTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
|
|
|
$ft = $pirep->flight_time;
|
2017-07-05 02:57:08 +08:00
|
|
|
$pilot = $pirep->pilot;
|
2017-07-04 14:05:37 +08:00
|
|
|
|
2017-12-14 00:56:26 +08:00
|
|
|
$this->pilotSvc->adjustFlightTime($pilot, $ft);
|
2017-07-04 14:05:37 +08:00
|
|
|
$this->pilotSvc->adjustFlightCount($pilot, +1);
|
|
|
|
$this->pilotSvc->calculatePilotRank($pilot);
|
|
|
|
$pirep->pilot->refresh();
|
|
|
|
|
|
|
|
# Change the status
|
2017-12-20 10:19:36 +08:00
|
|
|
$pirep->state = PirepState::ACCEPTED;
|
2017-07-04 14:05:37 +08:00
|
|
|
$pirep->save();
|
2017-08-24 03:19:05 +08:00
|
|
|
$pirep->refresh();
|
2017-07-04 14:05:37 +08:00
|
|
|
|
2017-12-26 05:19:34 +08:00
|
|
|
$this->setPilotState($pilot, $pirep);
|
2017-09-08 04:35:17 +08:00
|
|
|
|
2018-01-02 06:01:01 +08:00
|
|
|
Log::info('PIREP ' . $pirep->id . ' state change to ACCEPTED');
|
2017-12-03 14:48:33 +08:00
|
|
|
|
2018-01-11 02:39:13 +08:00
|
|
|
# Update the aircraft
|
2018-01-12 12:00:39 +08:00
|
|
|
$pirep->aircraft->flight_time += $pirep->flight_time;
|
2018-01-11 02:39:13 +08:00
|
|
|
$pirep->aircraft->airport_id = $pirep->arr_airport_id;
|
|
|
|
$pirep->aircraft->landing_time = $pirep->updated_at;
|
|
|
|
$pirep->aircraft->save();
|
|
|
|
|
2017-12-03 00:55:17 +08:00
|
|
|
event(new PirepAccepted($pirep));
|
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
return $pirep;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Pirep $pirep
|
|
|
|
* @return Pirep
|
|
|
|
*/
|
2017-12-14 00:56:26 +08:00
|
|
|
public function reject(Pirep $pirep): Pirep
|
2017-07-04 14:05:37 +08:00
|
|
|
{
|
|
|
|
# If this was previously ACCEPTED, then reconcile the flight hours
|
|
|
|
# that have already been counted, etc
|
2017-12-20 10:19:36 +08:00
|
|
|
if ($pirep->state === PirepState::ACCEPTED) {
|
2017-07-04 14:05:37 +08:00
|
|
|
$pilot = $pirep->pilot;
|
|
|
|
$ft = $pirep->flight_time * -1;
|
|
|
|
|
2017-12-14 00:56:26 +08:00
|
|
|
$this->pilotSvc->adjustFlightTime($pilot, $ft);
|
2017-07-04 14:05:37 +08:00
|
|
|
$this->pilotSvc->adjustFlightCount($pilot, -1);
|
|
|
|
$this->pilotSvc->calculatePilotRank($pilot);
|
|
|
|
$pirep->pilot->refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
# Change the status
|
2017-12-20 10:19:36 +08:00
|
|
|
$pirep->state = PirepState::REJECTED;
|
2017-07-04 14:05:37 +08:00
|
|
|
$pirep->save();
|
2017-08-24 03:19:05 +08:00
|
|
|
$pirep->refresh();
|
2017-07-04 14:05:37 +08:00
|
|
|
|
2018-01-12 12:00:39 +08:00
|
|
|
$pirep->aircraft->flight_time -= $pirep->flight_time;
|
|
|
|
$pirep->aircraft->save();
|
|
|
|
|
2017-12-20 10:19:36 +08:00
|
|
|
Log::info('PIREP ' . $pirep->id . ' state change to REJECTED');
|
2017-12-03 14:48:33 +08:00
|
|
|
|
2017-12-03 00:55:17 +08:00
|
|
|
event(new PirepRejected($pirep));
|
|
|
|
|
2017-07-04 14:05:37 +08:00
|
|
|
return $pirep;
|
2017-06-10 14:50:00 +08:00
|
|
|
}
|
2017-07-11 07:54:51 +08:00
|
|
|
|
2017-12-03 14:48:33 +08:00
|
|
|
/**
|
|
|
|
* @param Pirep $pirep
|
|
|
|
*/
|
2017-12-26 05:19:34 +08:00
|
|
|
public function setPilotState(User $pilot, Pirep $pirep)
|
2017-12-03 14:48:33 +08:00
|
|
|
{
|
2017-08-24 03:19:05 +08:00
|
|
|
$pilot->refresh();
|
2017-12-03 14:48:33 +08:00
|
|
|
|
2017-12-23 06:55:47 +08:00
|
|
|
$previous_airport = $pilot->curr_airport_id;
|
2017-08-24 03:19:05 +08:00
|
|
|
$pilot->curr_airport_id = $pirep->arr_airport_id;
|
|
|
|
$pilot->last_pirep_id = $pirep->id;
|
|
|
|
$pilot->save();
|
2017-07-11 07:54:51 +08:00
|
|
|
|
2017-12-26 05:19:34 +08:00
|
|
|
$pirep->refresh();
|
|
|
|
|
2017-12-23 06:55:47 +08:00
|
|
|
event(new UserStatsChanged($pilot, 'airport', $previous_airport));
|
2017-07-11 07:54:51 +08:00
|
|
|
}
|
2017-06-10 14:50:00 +08:00
|
|
|
}
|