Add first pass of pirep import; additional fields in flight/pirep tables #114

This commit is contained in:
Nabeel Shahzad
2018-01-29 18:14:55 -06:00
parent 5c164e2cf6
commit a5f51f6264
10 changed files with 206 additions and 30 deletions
+150 -13
View File
@@ -3,12 +3,16 @@
namespace App\Console\Services; namespace App\Console\Services;
use PDO; use PDO;
use Carbon\Carbon;
use Doctrine\DBAL\Driver\PDOException; use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutput;
use App\Models\Enums\FlightType;
use App\Models\Enums\PirepSource;
use App\Models\Pirep;
use App\Models\Aircraft; use App\Models\Aircraft;
use App\Models\Airline; use App\Models\Airline;
use App\Models\Airport; use App\Models\Airport;
@@ -66,7 +70,7 @@ class Importer
# The db credentials # The db credentials
$this->creds = array_merge([ $this->creds = array_merge([
'host' => 'localhost', 'host' => '127.0.0.1',
'port' => 3306, 'port' => 3306,
'name' => '', 'name' => '',
'user' => '', 'user' => '',
@@ -93,6 +97,7 @@ class Importer
$this->importPireps(); $this->importPireps();
# Finish up # Finish up
$this->findLastPireps();
$this->recalculateRanks(); $this->recalculateRanks();
} }
@@ -214,6 +219,39 @@ class Importer
return 0; return 0;
} }
/**
* @param $date
* @return Carbon
*/
protected function parseDate($date)
{
$carbon = Carbon::parse($date);
return $carbon;
}
/**
* Take a decimal duration and convert it to minutes
* @param $duration
* @return float|int
*/
protected function convertDuration($duration)
{
if(strpos($duration, '.') !== false) {
$delim = '.';
} elseif(strpos($duration, ':')) {
$delim = ':';
} else {
# no delimiter, assume it's just a straight hour
return (int) $duration * 60;
}
$hm = explode($delim, $duration);
$hours = (int) $hm[0] * 60;
$mins = (int) $hm[1];
return $hours + $mins;
}
/** /**
* @param $table * @param $table
* @return mixed * @return mixed
@@ -232,19 +270,24 @@ class Importer
/** /**
* Read all the rows in a table, but read them in a batched manner * Read all the rows in a table, but read them in a batched manner
* @param string $table The name of the table * @param string $table The name of the table
* @param null $read_rows Number of rows to read
* @return \Generator * @return \Generator
*/ */
protected function readRows($table) protected function readRows($table, $read_rows=null)
{ {
// Set the table prefix if it has been entered // Set the table prefix if it has been entered
$this->tableName($table); $this->tableName($table);
$offset = 0; $offset = 0;
if($read_rows === null) {
$read_rows = self::BATCH_READ_ROWS;
}
$total_rows = $this->getTotalRows($table); $total_rows = $this->getTotalRows($table);
while($offset < $total_rows) while($offset < $total_rows)
{ {
$rows_to_read = $offset+self::BATCH_READ_ROWS; $rows_to_read = $offset + $read_rows;
if($rows_to_read > $total_rows) { if($rows_to_read > $total_rows) {
$rows_to_read = $total_rows; $rows_to_read = $total_rows;
} }
@@ -398,7 +441,12 @@ class Importer
'hub' => $row->hub, 'hub' => $row->hub,
]; ];
if($this->saveModel(new Airport($attrs))) { $airport = Airport::updateOrCreate(
['id' => $attrs['id']],
$attrs
);
if($airport->wasRecentlyCreated) {
++$count; ++$count;
} }
} }
@@ -418,6 +466,8 @@ class Importer
{ {
$airline_id = $this->getMapping('airlines', $row->code); $airline_id = $this->getMapping('airlines', $row->code);
$flight_num = trim($row->flightnum);
$attrs = [ $attrs = [
'dpt_airport_id' => $row->depicao, 'dpt_airport_id' => $row->depicao,
'arr_airport_id' => $row->arricao, 'arr_airport_id' => $row->arricao,
@@ -426,15 +476,19 @@ class Importer
'level' => $row->flightlevel ?: 0, 'level' => $row->flightlevel ?: 0,
'dpt_time' => $row->deptime ?: '', 'dpt_time' => $row->deptime ?: '',
'arr_time' => $row->arrtime ?: '', 'arr_time' => $row->arrtime ?: '',
'flight_time' => $row->flighttime ?: '', 'flight_time' => $this->convertDuration($row->flighttime) ?: '',
'notes' => $row->notes ?: '', 'notes' => $row->notes ?: '',
'active' => $row->enabled ?: true, 'active' => $row->enabled ?: true,
]; ];
$flight = Flight::firstOrCreate( try {
['airline_id' => $airline_id, 'flight_number' => $row->flightnum], $flight = Flight::updateOrCreate(
$attrs ['airline_id' => $airline_id, 'flight_number' => $flight_num],
); $attrs
);
} catch (\Exception $e) {
#$this->error($e);
}
$this->addMapping('flights', $row->id, $flight->id); $this->addMapping('flights', $row->id, $flight->id);
@@ -453,15 +507,88 @@ class Importer
*/ */
protected function importPireps() protected function importPireps()
{ {
/*$this->comment('--- PIREP IMPORT ---'); $this->comment('--- PIREP IMPORT ---');
$count = 0; $count = 0;
foreach ($this->readRows('pireps') as $row) foreach ($this->readRows('pireps') as $row)
{ {
$pirep_id = $row->pirepid;
$user_id = $this->getMapping('users', $row->pilotid);
$airline_id = $this->getMapping('airlines', $row->code);
$aircraft_id = $this->getMapping('aircraft', $row->aircraft);
$attrs = [
#'id' => $pirep_id,
'user_id' => $user_id,
'airline_id' => $airline_id,
'aircraft_id' => $aircraft_id,
'flight_number' => $row->flightnum ?: '',
'dpt_airport_id' => $row->depicao,
'arr_airport_id' => $row->arricao,
'fuel_used' => $row->fuelused,
'route' => $row->route ?: '',
'source_name' => $row->source,
'created_at' => $this->parseDate($row->submitdate),
'updated_at' => $this->parseDate($row->modifieddate),
];
# Set the distance
$distance = round($row->distance ?: 0, 2);
$attrs['distance'] = $distance;
$attrs['planned_distance'] = $distance;
# Set the flight time properly
$duration = $this->convertDuration($row->flighttime_stamp);
$attrs['flight_time'] = $duration;
$attrs['planned_flight_time'] = $duration;
# Set how it was filed
if(strtoupper($row->source) === 'MANUAL') {
$attrs['source'] = PirepSource::MANUAL;
} else {
$attrs['source'] = PirepSource::ACARS;
}
# Set the flight type
$row->flighttype = strtoupper($row->flighttype);
if($row->flighttype === 'P') {
$attrs['flight_type'] = FlightType::PASSENGER;
} elseif($row->flighttype === 'C') {
$attrs['flight_type'] = FlightType::CARGO;
} else {
$attrs['flight_type'] = FlightType::CHARTER;
}
# Set the flight level of the PIREP is set
if(property_exists($row, 'flightlevel')) {
$attrs['level'] = $row->flightlevel;
} else {
$attrs['level'] = 0;
}
$pirep = Pirep::updateOrCreate(
['id' => $pirep_id],
$attrs
);
$source = strtoupper($row->source);
if($source === 'SMARTCARS') {
# TODO: Parse smartcars log into the acars table
} elseif($source === 'KACARS') {
# TODO: Parse kACARS log into acars table
} elseif($source === 'XACARS') {
# TODO: Parse XACARS log into acars table
}
# TODO: Add extra fields in as PIREP fields
$this->addMapping('pireps', $row->pirepid, $pirep->id);
if ($pirep->wasRecentlyCreated) {
++$count;
}
} }
$this->info('Imported ' . $count . ' pireps');*/ $this->info('Imported ' . $count . ' pireps');
} }
protected function importUsers() protected function importUsers()
@@ -469,7 +596,8 @@ class Importer
$this->comment('--- USER IMPORT ---'); $this->comment('--- USER IMPORT ---');
$count = 0; $count = 0;
foreach ($this->readRows('pilots') as $row) { foreach ($this->readRows('pilots', 50) as $row) {
# TODO: What to do about pilot ids # TODO: What to do about pilot ids
$name = $row->firstname . ' ' . $row->lastname; $name = $row->firstname . ' ' . $row->lastname;
@@ -491,9 +619,10 @@ class Importer
'flights' => (int)$row->totalflights, 'flights' => (int)$row->totalflights,
'flight_time' => Utils::hoursToMinutes($row->totalhours), 'flight_time' => Utils::hoursToMinutes($row->totalhours),
'state' => $state, 'state' => $state,
'created_at' => $this->parseDate($row->joindate),
]; ];
$user = User::firstOrCreate( $user = User::updateOrCreate(
['email' => $row->email], ['email' => $row->email],
$attrs $attrs
); );
@@ -508,6 +637,14 @@ class Importer
$this->info('Imported ' . $count . ' users'); $this->info('Imported ' . $count . ' users');
} }
/**
* Go through and set the last PIREP ID for the users
*/
protected function findLastPireps()
{
}
/** /**
* Recalculate all of the user ranks * Recalculate all of the user ranks
*/ */
@@ -1,5 +1,7 @@
<?php <?php
use App\Models\Enums\FlightType;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -27,6 +29,7 @@ class CreateFlightTables extends Migration
$table->unsignedInteger('level')->nullable()->default(0); $table->unsignedInteger('level')->nullable()->default(0);
$table->unsignedDecimal('distance', 19)->nullable()->default(0.0); $table->unsignedDecimal('distance', 19)->nullable()->default(0.0);
$table->unsignedDecimal('flight_time', 19)->nullable(); $table->unsignedDecimal('flight_time', 19)->nullable();
$table->tinyInteger('flight_type')->default(FlightType::PASSENGER);
$table->text('route')->nullable(); $table->text('route')->nullable();
$table->text('notes')->nullable(); $table->text('notes')->nullable();
$table->boolean('has_bid')->default(false); $table->boolean('has_bid')->default(false);
@@ -1,5 +1,6 @@
<?php <?php
use App\Models\Enums\FlightType;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus; use App\Models\Enums\PirepStatus;
@@ -35,9 +36,12 @@ class CreatePirepTables extends Migration
$table->unsignedDecimal('planned_flight_time', 19)->nullable(); $table->unsignedDecimal('planned_flight_time', 19)->nullable();
$table->unsignedDecimal('gross_weight', 19)->nullable(); $table->unsignedDecimal('gross_weight', 19)->nullable();
$table->unsignedDecimal('fuel_used', 19)->nullable(); $table->unsignedDecimal('fuel_used', 19)->nullable();
$table->decimal('landing_rate', 19)->nullable();
$table->text('route')->nullable(); $table->text('route')->nullable();
$table->text('notes')->nullable(); $table->text('notes')->nullable();
$table->unsignedTinyInteger('source')->nullable()->default(0); $table->unsignedTinyInteger('source')->nullable()->default(0);
$table->string('source_name', 20)->nullable();
$table->tinyInteger('flight_type')->default(FlightType::PASSENGER);
$table->tinyInteger('state')->default(PirepState::PENDING); $table->tinyInteger('state')->default(PirepState::PENDING);
$table->tinyInteger('status')->default(PirepStatus::SCHEDULED); $table->tinyInteger('status')->default(PirepStatus::SCHEDULED);
$table->longText('raw_data')->nullable(); $table->longText('raw_data')->nullable();
+9 -6
View File
@@ -22,21 +22,24 @@ class FileRequest extends FormRequest
{ {
$rules = [ $rules = [
'flight_time' => 'required|integer', 'flight_time' => 'required|integer',
'distance' => 'required|numeric',
'airline_id' => 'nullable|exists:airlines,id',
'aircraft_id' => 'nullable|exists:aircraft,id',
'flight_id' => 'nullable|exists:flights,id',
'flight_number' => 'nullable', 'flight_number' => 'nullable',
'dpt_airport_id' => 'nullable', 'dpt_airport_id' => 'nullable',
'arr_airport_id' => 'nullable', 'arr_airport_id' => 'nullable',
'airline_id' => 'nullable|exists:airlines,id',
'aircraft_id' => 'nullable|exists:aircraft,id',
'flight_id' => 'nullable',
'route_code' => 'nullable', 'route_code' => 'nullable',
'route_leg' => 'nullable', 'route_leg' => 'nullable',
'distance' => 'nullable|numeric',
'planned_distance' => 'nullable|numeric', 'planned_distance' => 'nullable|numeric',
'flight_time' => 'nullable|integer',
'planned_flight_time' => 'nullable|integer', 'planned_flight_time' => 'nullable|integer',
'level' => 'nullable', 'level' => 'nullable|numeric',
'route' => 'nullable', 'route' => 'nullable',
'notes' => 'nullable', 'notes' => 'nullable',
'source_name' => 'nullable|max:20',
'landing_rate' => 'nullable|numeric',
'flight_type' => 'nullable|integer',
'created_at' => 'nullable|date', 'created_at' => 'nullable|date',
]; ];
+7 -4
View File
@@ -20,19 +20,22 @@ class PrefileRequest extends FormRequest
$rules = [ $rules = [
'airline_id' => 'required|exists:airlines,id', 'airline_id' => 'required|exists:airlines,id',
'aircraft_id' => 'required|exists:aircraft,id', 'aircraft_id' => 'required|exists:aircraft,id',
'flight_number' => 'required',
'level' => 'required|numeric',
'dpt_airport_id' => 'required', 'dpt_airport_id' => 'required',
'arr_airport_id' => 'required', 'arr_airport_id' => 'required',
'flight_id' => 'nullable', 'planned_distance' => 'required|numeric',
'flight_number' => 'required', 'source_name' => 'required|max:20',
'flight_id' => 'nullable|exists:flights,id',
'route_code' => 'nullable', 'route_code' => 'nullable',
'route_leg' => 'nullable', 'route_leg' => 'nullable',
'distance' => 'nullable|numeric', 'distance' => 'nullable|numeric',
'planned_distance' => 'nullable|numeric',
'flight_time' => 'nullable|integer', 'flight_time' => 'nullable|integer',
'planned_flight_time' => 'nullable|integer', 'planned_flight_time' => 'nullable|integer',
'level' => 'required|integer',
'route' => 'nullable', 'route' => 'nullable',
'notes' => 'nullable', 'notes' => 'nullable',
'flight_type' => 'nullable|integer',
'created_at' => 'nullable|date', 'created_at' => 'nullable|date',
]; ];
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace App\Models\Enums;
class FlightType extends EnumBase {
const PASSENGER = 0;
const CARGO = 1;
const CHARTER = 2;
protected static $labels = [
FlightType::PASSENGER => 'Passenger',
FlightType::CARGO => 'Cargo',
FlightType::CHARTER => 'Charter',
];
}
+4 -3
View File
@@ -11,9 +11,8 @@ class Flight extends BaseModel
public $table = 'flights'; public $table = 'flights';
public $incrementing = false; public $incrementing = false;
protected $dates = ['deleted_at'];
public $fillable = [ public $fillable = [
'id',
'airline_id', 'airline_id',
'flight_number', 'flight_number',
'route_code', 'route_code',
@@ -21,11 +20,12 @@ class Flight extends BaseModel
'dpt_airport_id', 'dpt_airport_id',
'arr_airport_id', 'arr_airport_id',
'alt_airport_id', 'alt_airport_id',
'route',
'dpt_time', 'dpt_time',
'arr_time', 'arr_time',
'level', 'level',
'distance', 'distance',
'flight_type',
'route',
'notes', 'notes',
'has_bid', 'has_bid',
'active', 'active',
@@ -35,6 +35,7 @@ class Flight extends BaseModel
'flight_number' => 'integer', 'flight_number' => 'integer',
'level' => 'integer', 'level' => 'integer',
'distance' => 'float', 'distance' => 'float',
'flight_type' => 'integer',
'has_bid' => 'boolean', 'has_bid' => 'boolean',
'active' => 'boolean', 'active' => 'boolean',
]; ];
+8
View File
@@ -23,6 +23,7 @@ class Pirep extends BaseModel
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
public $fillable = [ public $fillable = [
'id',
'user_id', 'user_id',
'flight_id', 'flight_id',
'flight_number', 'flight_number',
@@ -38,13 +39,18 @@ class Pirep extends BaseModel
'dpt_airport_id', 'dpt_airport_id',
'arr_airport_id', 'arr_airport_id',
'fuel_used', 'fuel_used',
'landing_rate',
'source', 'source',
'level', 'level',
'route', 'route',
'notes', 'notes',
'flight_type',
'state', 'state',
'status', 'status',
'source_name',
'raw_data', 'raw_data',
'created_at',
'updated_at',
]; ];
protected $casts = [ protected $casts = [
@@ -57,6 +63,8 @@ class Pirep extends BaseModel
'altitude' => 'integer', 'altitude' => 'integer',
'fuel_used' => 'float', 'fuel_used' => 'float',
'gross_weight' => 'float', 'gross_weight' => 'float',
'landing_rate' => 'float',
'flight_type' => 'integer',
'source' => 'integer', 'source' => 'integer',
'state' => 'integer', 'state' => 'integer',
'status' => 'integer', 'status' => 'integer',
+2 -4
View File
@@ -25,10 +25,8 @@ trait HashId
{ {
parent::boot(); parent::boot();
static::creating(function ($model) { static::creating(function ($model) {
$key = $model->getKeyName(); if (empty($model->id)) {
if (empty($model->{$key})) { $model->id = static::createNewHashId();
$id = static::createNewHashId();
$model->{$key} = $id;
} }
}); });
} }
+2
View File
@@ -47,6 +47,8 @@ class User extends Authenticatable
'timezone', 'timezone',
'state', 'state',
'status', 'status',
'created_at',
'updated_at',
]; ];
/** /**