diff --git a/app/Console/Services/Importer.php b/app/Console/Services/Importer.php index cbb8d74b..d1f75fbc 100644 --- a/app/Console/Services/Importer.php +++ b/app/Console/Services/Importer.php @@ -3,12 +3,16 @@ namespace App\Console\Services; use PDO; +use Carbon\Carbon; use Doctrine\DBAL\Driver\PDOException; use Illuminate\Support\Str; use Illuminate\Database\QueryException; use Illuminate\Support\Facades\Hash; 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\Airline; use App\Models\Airport; @@ -66,7 +70,7 @@ class Importer # The db credentials $this->creds = array_merge([ - 'host' => 'localhost', + 'host' => '127.0.0.1', 'port' => 3306, 'name' => '', 'user' => '', @@ -93,6 +97,7 @@ class Importer $this->importPireps(); # Finish up + $this->findLastPireps(); $this->recalculateRanks(); } @@ -214,6 +219,39 @@ class Importer 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 * @return mixed @@ -232,19 +270,24 @@ class Importer /** * Read all the rows in a table, but read them in a batched manner * @param string $table The name of the table + * @param null $read_rows Number of rows to read * @return \Generator */ - protected function readRows($table) + protected function readRows($table, $read_rows=null) { // Set the table prefix if it has been entered $this->tableName($table); $offset = 0; + if($read_rows === null) { + $read_rows = self::BATCH_READ_ROWS; + } + $total_rows = $this->getTotalRows($table); while($offset < $total_rows) { - $rows_to_read = $offset+self::BATCH_READ_ROWS; + $rows_to_read = $offset + $read_rows; if($rows_to_read > $total_rows) { $rows_to_read = $total_rows; } @@ -398,7 +441,12 @@ class Importer 'hub' => $row->hub, ]; - if($this->saveModel(new Airport($attrs))) { + $airport = Airport::updateOrCreate( + ['id' => $attrs['id']], + $attrs + ); + + if($airport->wasRecentlyCreated) { ++$count; } } @@ -418,6 +466,8 @@ class Importer { $airline_id = $this->getMapping('airlines', $row->code); + $flight_num = trim($row->flightnum); + $attrs = [ 'dpt_airport_id' => $row->depicao, 'arr_airport_id' => $row->arricao, @@ -426,15 +476,19 @@ class Importer 'level' => $row->flightlevel ?: 0, 'dpt_time' => $row->deptime ?: '', 'arr_time' => $row->arrtime ?: '', - 'flight_time' => $row->flighttime ?: '', + 'flight_time' => $this->convertDuration($row->flighttime) ?: '', 'notes' => $row->notes ?: '', 'active' => $row->enabled ?: true, ]; - $flight = Flight::firstOrCreate( - ['airline_id' => $airline_id, 'flight_number' => $row->flightnum], - $attrs - ); + try { + $flight = Flight::updateOrCreate( + ['airline_id' => $airline_id, 'flight_number' => $flight_num], + $attrs + ); + } catch (\Exception $e) { + #$this->error($e); + } $this->addMapping('flights', $row->id, $flight->id); @@ -453,15 +507,88 @@ class Importer */ protected function importPireps() { - /*$this->comment('--- PIREP IMPORT ---'); + $this->comment('--- PIREP IMPORT ---'); $count = 0; 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() @@ -469,7 +596,8 @@ class Importer $this->comment('--- USER IMPORT ---'); $count = 0; - foreach ($this->readRows('pilots') as $row) { + foreach ($this->readRows('pilots', 50) as $row) { + # TODO: What to do about pilot ids $name = $row->firstname . ' ' . $row->lastname; @@ -491,9 +619,10 @@ class Importer 'flights' => (int)$row->totalflights, 'flight_time' => Utils::hoursToMinutes($row->totalhours), 'state' => $state, + 'created_at' => $this->parseDate($row->joindate), ]; - $user = User::firstOrCreate( + $user = User::updateOrCreate( ['email' => $row->email], $attrs ); @@ -508,6 +637,14 @@ class Importer $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 */ diff --git a/app/Database/migrations/2017_06_17_214650_create_flight_tables.php b/app/Database/migrations/2017_06_17_214650_create_flight_tables.php index 81e97ede..3e515f41 100644 --- a/app/Database/migrations/2017_06_17_214650_create_flight_tables.php +++ b/app/Database/migrations/2017_06_17_214650_create_flight_tables.php @@ -1,5 +1,7 @@ unsignedInteger('level')->nullable()->default(0); $table->unsignedDecimal('distance', 19)->nullable()->default(0.0); $table->unsignedDecimal('flight_time', 19)->nullable(); + $table->tinyInteger('flight_type')->default(FlightType::PASSENGER); $table->text('route')->nullable(); $table->text('notes')->nullable(); $table->boolean('has_bid')->default(false); diff --git a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php index 0baaf1fc..acdfd279 100644 --- a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php +++ b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php @@ -1,5 +1,6 @@ unsignedDecimal('planned_flight_time', 19)->nullable(); $table->unsignedDecimal('gross_weight', 19)->nullable(); $table->unsignedDecimal('fuel_used', 19)->nullable(); + $table->decimal('landing_rate', 19)->nullable(); $table->text('route')->nullable(); $table->text('notes')->nullable(); $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('status')->default(PirepStatus::SCHEDULED); $table->longText('raw_data')->nullable(); diff --git a/app/Http/Requests/Acars/FileRequest.php b/app/Http/Requests/Acars/FileRequest.php index f74d7d48..2cbf7a91 100644 --- a/app/Http/Requests/Acars/FileRequest.php +++ b/app/Http/Requests/Acars/FileRequest.php @@ -22,21 +22,24 @@ class FileRequest extends FormRequest { $rules = [ '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', 'dpt_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_leg' => 'nullable', - 'distance' => 'nullable|numeric', 'planned_distance' => 'nullable|numeric', - 'flight_time' => 'nullable|integer', 'planned_flight_time' => 'nullable|integer', - 'level' => 'nullable', + 'level' => 'nullable|numeric', 'route' => 'nullable', 'notes' => 'nullable', + 'source_name' => 'nullable|max:20', + 'landing_rate' => 'nullable|numeric', + 'flight_type' => 'nullable|integer', 'created_at' => 'nullable|date', ]; diff --git a/app/Http/Requests/Acars/PrefileRequest.php b/app/Http/Requests/Acars/PrefileRequest.php index d37674a6..27e95a2a 100644 --- a/app/Http/Requests/Acars/PrefileRequest.php +++ b/app/Http/Requests/Acars/PrefileRequest.php @@ -20,19 +20,22 @@ class PrefileRequest extends FormRequest $rules = [ 'airline_id' => 'required|exists:airlines,id', 'aircraft_id' => 'required|exists:aircraft,id', + 'flight_number' => 'required', + 'level' => 'required|numeric', 'dpt_airport_id' => 'required', 'arr_airport_id' => 'required', - 'flight_id' => 'nullable', - 'flight_number' => 'required', + 'planned_distance' => 'required|numeric', + 'source_name' => 'required|max:20', + + 'flight_id' => 'nullable|exists:flights,id', 'route_code' => 'nullable', 'route_leg' => 'nullable', 'distance' => 'nullable|numeric', - 'planned_distance' => 'nullable|numeric', 'flight_time' => 'nullable|integer', 'planned_flight_time' => 'nullable|integer', - 'level' => 'required|integer', 'route' => 'nullable', 'notes' => 'nullable', + 'flight_type' => 'nullable|integer', 'created_at' => 'nullable|date', ]; diff --git a/app/Models/Enums/FlightType.php b/app/Models/Enums/FlightType.php new file mode 100644 index 00000000..7e0a207e --- /dev/null +++ b/app/Models/Enums/FlightType.php @@ -0,0 +1,17 @@ + 'Passenger', + FlightType::CARGO => 'Cargo', + FlightType::CHARTER => 'Charter', + ]; +} diff --git a/app/Models/Flight.php b/app/Models/Flight.php index de67f2ff..56dadc5e 100644 --- a/app/Models/Flight.php +++ b/app/Models/Flight.php @@ -11,9 +11,8 @@ class Flight extends BaseModel public $table = 'flights'; public $incrementing = false; - protected $dates = ['deleted_at']; - public $fillable = [ + 'id', 'airline_id', 'flight_number', 'route_code', @@ -21,11 +20,12 @@ class Flight extends BaseModel 'dpt_airport_id', 'arr_airport_id', 'alt_airport_id', - 'route', 'dpt_time', 'arr_time', 'level', 'distance', + 'flight_type', + 'route', 'notes', 'has_bid', 'active', @@ -35,6 +35,7 @@ class Flight extends BaseModel 'flight_number' => 'integer', 'level' => 'integer', 'distance' => 'float', + 'flight_type' => 'integer', 'has_bid' => 'boolean', 'active' => 'boolean', ]; diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index 6f131697..4be4cb62 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -23,6 +23,7 @@ class Pirep extends BaseModel protected $dates = ['deleted_at']; public $fillable = [ + 'id', 'user_id', 'flight_id', 'flight_number', @@ -38,13 +39,18 @@ class Pirep extends BaseModel 'dpt_airport_id', 'arr_airport_id', 'fuel_used', + 'landing_rate', 'source', 'level', 'route', 'notes', + 'flight_type', 'state', 'status', + 'source_name', 'raw_data', + 'created_at', + 'updated_at', ]; protected $casts = [ @@ -57,6 +63,8 @@ class Pirep extends BaseModel 'altitude' => 'integer', 'fuel_used' => 'float', 'gross_weight' => 'float', + 'landing_rate' => 'float', + 'flight_type' => 'integer', 'source' => 'integer', 'state' => 'integer', 'status' => 'integer', diff --git a/app/Models/Traits/HashId.php b/app/Models/Traits/HashId.php index bec914cd..67e64363 100644 --- a/app/Models/Traits/HashId.php +++ b/app/Models/Traits/HashId.php @@ -25,10 +25,8 @@ trait HashId { parent::boot(); static::creating(function ($model) { - $key = $model->getKeyName(); - if (empty($model->{$key})) { - $id = static::createNewHashId(); - $model->{$key} = $id; + if (empty($model->id)) { + $model->id = static::createNewHashId(); } }); } diff --git a/app/Models/User.php b/app/Models/User.php index 068d64b8..9ec25441 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -47,6 +47,8 @@ class User extends Authenticatable 'timezone', 'state', 'status', + 'created_at', + 'updated_at', ]; /**