From 55250b8789ed8f37e9375b18a1ba13bc7b6e3b80 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 13 Dec 2017 10:56:26 -0600 Subject: [PATCH] PIREP tests working, using minutes to track flight hours instead of seconds --- app/Facades/Utils.php | 45 +++++++- .../Controllers/Admin/PirepController.php | 9 +- .../Controllers/Frontend/PirepController.php | 5 +- app/Models/Pirep.php | 1 + app/Services/PIREPService.php | 12 +-- app/Services/UserService.php | 13 +-- database/factories/PirepFactory.php | 11 +- database/factories/UserFactory.php | 2 + .../layouts/default/dashboard/index.blade.php | 2 +- .../layouts/default/profile/index.blade.php | 2 +- tests/PIREPTest.php | 102 ++++++++---------- tests/UtilsTest.php | 8 +- tests/data/base.yml | 68 ------------ 13 files changed, 124 insertions(+), 156 deletions(-) diff --git a/app/Facades/Utils.php b/app/Facades/Utils.php index 74433158..ac77b917 100644 --- a/app/Facades/Utils.php +++ b/app/Facades/Utils.php @@ -21,6 +21,11 @@ class Utils extends Facade return $key; } + public static function minutesToTimeParts($minutes): array + { + return self::secondsToTimeParts(self::minutesToSeconds($minutes)); + } + /** * Convert seconds to an array of hours, minutes, seconds * @param $seconds @@ -47,7 +52,7 @@ class Utils extends Facade * @param bool $incl_sec * @return string */ - public static function secondsToTime($seconds, $incl_sec=false): string + public static function secondsToTimeString($seconds, $incl_sec=false): string { $hms = self::secondsToTimeParts($seconds); $format = $hms['h'].'h '.$hms['m'].'m'; @@ -58,6 +63,44 @@ class Utils extends Facade return $format; } + /** + * @param $minutes + * @return float|int + */ + public static function minutesToSeconds($minutes) + { + return $minutes * 60; + } + + /** + * Convert the seconds to minutes and then round it up + * @param $seconds + * @return float|int + */ + public static function secondsToMinutes($seconds) + { + return ceil($seconds/60); + } + + /** + * Convert hours to minutes. Pretty complex + * @param $minutes + * @return float|int + */ + public static function minutesToHours($minutes) + { + return $minutes/60; + } + + /** + * @param $hours + * @return float|int + */ + public static function hoursToMinutes($hours) + { + return $hours * 60; + } + /** * Bitwise operator for setting days of week to integer field * @param int $datefield initial datefield diff --git a/app/Http/Controllers/Admin/PirepController.php b/app/Http/Controllers/Admin/PirepController.php index 19417df4..e4157e61 100644 --- a/app/Http/Controllers/Admin/PirepController.php +++ b/app/Http/Controllers/Admin/PirepController.php @@ -109,6 +109,9 @@ class PirepController extends BaseController $input = $request->all(); $pirep = $this->pirepRepo->create($input); + $pirep->flight_time = ((int) Utils::hoursToMinutes($request['hours'])) + + ((int) $request['minutes']); + Flash::success('Pirep saved successfully.'); return redirect(route('admin.pireps.index')); } @@ -145,7 +148,7 @@ class PirepController extends BaseController return redirect(route('admin.pireps.index')); } - $hms = Utils::secondsToTimeParts($pirep->flight_time); + $hms = Utils::minutesToTimeParts($pirep->flight_time); $pirep->hours = $hms['h']; $pirep->minutes = $hms['m']; @@ -167,8 +170,8 @@ class PirepController extends BaseController { $pirep = $this->pirepRepo->findWithoutFail($id); - $pirep->flight_time = ((int)$request['hours'] * 60 * 60) - + ((int)$request['minutes'] * 60); + $pirep->flight_time = ((int) Utils::hoursToMinutes($request['hours'])) + + ((int) $request['minutes']); if (empty($pirep)) { Flash::error('Pirep not found'); diff --git a/app/Http/Controllers/Frontend/PirepController.php b/app/Http/Controllers/Frontend/PirepController.php index 8131821c..4492ad37 100644 --- a/app/Http/Controllers/Frontend/PirepController.php +++ b/app/Http/Controllers/Frontend/PirepController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Frontend; +use App\Facades\Utils; use App\Repositories\Criteria\WhereCriteria; use App\Services\PIREPService; use Illuminate\Support\Facades\Auth; @@ -77,8 +78,8 @@ class PirepController extends Controller // Any special fields $pirep->pilot()->associate(Auth::user()); - $pirep->flight_time = ((int)$pirep_fields['hours'] * 60 * 60) - + ((int)$pirep_fields['minutes'] * 60); + $pirep->flight_time = ((int) Utils::hoursToMinutes($request['hours'])) + + ((int) $request['minutes']); // The custom fields from the form $custom_fields = []; diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index e6d70933..c45e5791 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -47,6 +47,7 @@ class Pirep extends Model * @var array */ protected $casts = [ + 'id' => 'string', 'flight_time' => 'integer', 'level' => 'integer', 'fuel_used' => 'integer', diff --git a/app/Services/PIREPService.php b/app/Services/PIREPService.php index f1a5cd44..664148ea 100644 --- a/app/Services/PIREPService.php +++ b/app/Services/PIREPService.php @@ -38,7 +38,7 @@ class PIREPService extends BaseService * * @return Pirep */ - public function create(Pirep &$pirep, array $field_values): Pirep + public function create(Pirep $pirep, array $field_values=[]): Pirep { if($field_values === null) { $field_values = []; @@ -85,7 +85,7 @@ class PIREPService extends BaseService * @param int $new_status * @return Pirep */ - public function changeStatus(Pirep &$pirep, int $new_status): Pirep + public function changeStatus(Pirep $pirep, int $new_status): Pirep { Log::info('PIREP ' . $pirep->id . ' status change from '.$pirep->status.' to ' . $new_status); @@ -127,7 +127,7 @@ class PIREPService extends BaseService * @param Pirep $pirep * @return Pirep */ - public function accept(Pirep &$pirep): Pirep + public function accept(Pirep $pirep): Pirep { # moving from a REJECTED state to ACCEPTED, reconcile statuses if ($pirep->status === config('enums.pirep_status.ACCEPTED')) { @@ -137,7 +137,7 @@ class PIREPService extends BaseService $ft = $pirep->flight_time; $pilot = $pirep->pilot; - $this->pilotSvc->adjustFlightHours($pilot, $ft); + $this->pilotSvc->adjustFlightTime($pilot, $ft); $this->pilotSvc->adjustFlightCount($pilot, +1); $this->pilotSvc->calculatePilotRank($pilot); $pirep->pilot->refresh(); @@ -160,7 +160,7 @@ class PIREPService extends BaseService * @param Pirep $pirep * @return Pirep */ - public function reject(Pirep &$pirep): Pirep + public function reject(Pirep $pirep): Pirep { # If this was previously ACCEPTED, then reconcile the flight hours # that have already been counted, etc @@ -168,7 +168,7 @@ class PIREPService extends BaseService $pilot = $pirep->pilot; $ft = $pirep->flight_time * -1; - $this->pilotSvc->adjustFlightHours($pilot, $ft); + $this->pilotSvc->adjustFlightTime($pilot, $ft); $this->pilotSvc->adjustFlightCount($pilot, -1); $this->pilotSvc->calculatePilotRank($pilot); $pirep->pilot->refresh(); diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 7da58690..d0fb65c3 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -27,10 +27,10 @@ class UserService extends BaseService return $user; } - public function adjustFlightHours(User $user, int $hours): User + public function adjustFlightTime(User $user, int $minutes): User { $user->refresh(); - $user->flight_time += $hours; + $user->flight_time += $minutes; $user->save(); event(new UserStateChanged($user)); @@ -41,15 +41,10 @@ class UserService extends BaseService public function calculatePilotRank(User $user): User { $user->refresh(); - $pilot_hours = $user->flight_time / 3600; + $pilot_hours = Utils::minutesToHours($user->flight_time); # TODO: Cache - $ranks = Cache::remember( - config('cache.keys.RANKS_PILOT_LIST.key'), - config('cache.keys.RANKS_PILOT_LIST.time'), - function () { - return Rank::where('auto_promote', true)->orderBy('hours', 'asc')->get(); - }); + $ranks = Rank::where('auto_promote', true)->orderBy('hours', 'asc')->get(); foreach ($ranks as $rank) { if($rank->hours > $pilot_hours) { diff --git a/database/factories/PirepFactory.php b/database/factories/PirepFactory.php index 28d95329..31cd167c 100644 --- a/database/factories/PirepFactory.php +++ b/database/factories/PirepFactory.php @@ -15,7 +15,7 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) use ($airlines return [ 'id' => substr($faker->unique()->sha1, 0, 12), - 'airline_id' => $faker->randomElement($airlinesAvailable), + 'airline_id' => 1, #$faker->randomElement($airlinesAvailable), 'user_id' => function () { # OVERRIDE THIS IF NEEDED return factory(App\Models\User::class)->create()->id; }, @@ -26,19 +26,22 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) use ($airlines return factory(App\Models\Flight::class)->create()->flight_number; }, 'route_code' => function(array $pirep) { - return App\Models\Flight::where('flight_number', $pirep['flight_number'])->first()->route_code; + //return App\Models\Flight::where(['flight_number' => $pirep['flight_number']])->first()->route_code; }, 'route_leg' => function (array $pirep) { - return App\Models\Flight::where('flight_number', $pirep['flight_number'])->first()->route_leg; + //return App\Models\Flight::where('flight_number', $pirep['flight_number'])->first()->route_leg; }, 'dpt_airport_id' => function () { return factory(App\Models\Airport::class)->create()->id; }, + 'arr_airport_id' => function () { + return factory(App\Models\Airport::class)->create()->id; + }, 'flight_time' => $faker->randomFloat(2), 'route' => $faker->text(), 'notes' => $faker->text(), 'source' => $faker->randomElement([0, 1]), # MANUAL/ACARS - 'status' => $faker->randomElement([-1, 0, 1]), # REJECTED/PENDING/ACCEPTED + 'status' => config('enums.pirep_status.PENDING'), //$faker->randomElement([-1, 0, 1]), # REJECTED/PENDING/ACCEPTED 'raw_data' => $raw_data ?: $raw_data = json_encode(['key' => 'value']), 'created_at' => $faker->dateTimeBetween('-1 week', 'now'), 'updated_at' => function(array $pirep) { diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 12ad0442..ab310f17 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -12,6 +12,8 @@ $factory->define(App\Models\User::class, function (Faker $faker) 'email' => $faker->safeEmail, 'password' => $password ?: $password = Hash::make('secret'), 'api_key' => $faker->sha1, + 'airline_id' => 1, + 'rank_id' => 1, 'flights' => $faker->numberBetween(0, 1000), 'flight_time' => $faker->numberBetween(0, 10000), 'remember_token' => $faker->unique()->text(5), diff --git a/resources/views/layouts/default/dashboard/index.blade.php b/resources/views/layouts/default/dashboard/index.blade.php index 22ef00b2..160115f0 100644 --- a/resources/views/layouts/default/dashboard/index.blade.php +++ b/resources/views/layouts/default/dashboard/index.blade.php @@ -21,7 +21,7 @@
-

{!! \App\Facades\Utils::secondsToTime($user->flight_time, false)!!}

+

{!! \App\Facades\Utils::secondsToTimeString($user->flight_time, false)!!}

total hours
diff --git a/resources/views/layouts/default/profile/index.blade.php b/resources/views/layouts/default/profile/index.blade.php index cff190c5..8525e351 100644 --- a/resources/views/layouts/default/profile/index.blade.php +++ b/resources/views/layouts/default/profile/index.blade.php @@ -23,7 +23,7 @@
-

{!! \App\Facades\Utils::secondsToTime($user->flight_time, false)!!}

+

{!! \App\Facades\Utils::secondsToTimeString($user->flight_time, false)!!}

Flight Hours

diff --git a/tests/PIREPTest.php b/tests/PIREPTest.php index e8e9db51..7f7f08c5 100644 --- a/tests/PIREPTest.php +++ b/tests/PIREPTest.php @@ -12,41 +12,6 @@ class PIREPTest extends TestCase #use DatabaseMigrations; protected $pirepSvc; - protected $SAMPLE_PIREP - = [ - 'user_id' => 1, - 'airline_id' => 1, - 'flight_id' => 1, - 'aircraft_id' => 1, - 'dpt_airport_id' => 1, - 'arr_airport_id' => 2, - 'flight_time' => 21600, # 6 hours - 'source' => 0, # manual - 'fuel_used' => 100, - 'notes' => 'just a pilot report', - ]; - - /** - * Add $count number of PIREPs and return a User object - * @param int $count - * @param bool $accept - * - * @return User - */ - protected function addPIREP($count=1, $accept=true): User - { - for($i = 0; $i < $count; $i++) { - $pirep = new Pirep($this->SAMPLE_PIREP); - $pirep = $this->pirepSvc->create($pirep, []); - if($accept) { - $this->pirepSvc->changeStatus($pirep, - config('enums.pirep_status.ACCEPTED')); - } - } - - $pilot = User::where('id', $this->SAMPLE_PIREP['user_id'])->first(); - return $pilot; - } public function setUp() { @@ -59,32 +24,36 @@ class PIREPTest extends TestCase */ public function testAddPirep() { - $pirep = new Pirep($this->SAMPLE_PIREP); - $pirep->save(); - + $pirep = factory(App\Models\Pirep::class)->create(); $pirep = $this->pirepSvc->create($pirep, []); /** * Check the initial status info */ - $this->assertEquals($pirep->pilot->flights, 0); $this->assertEquals($pirep->status, config('enums.pirep_status.PENDING')); /** * Now set the PIREP state to ACCEPTED */ - $this->pirepSvc->changeStatus($pirep, "1"); - $this->assertEquals(1, $pirep->pilot->flights); - $this->assertEquals(21600, $pirep->pilot->flight_time); - $this->assertEquals(1, $pirep->pilot->rank_id); + $new_pirep_count = $pirep->pilot->flights + 1; + $original_flight_time = $pirep->pilot->flight_time ; + $new_flight_time = $pirep->pilot->flight_time + $pirep->flight_time; + + $this->pirepSvc->changeStatus($pirep, '1'); + $this->assertEquals($new_pirep_count, $pirep->pilot->flights); + $this->assertEquals($new_flight_time, $pirep->pilot->flight_time); + $this->assertEquals($pirep->arr_airport_id, $pirep->pilot->curr_airport_id); + #$this->assertEquals(1, $pirep->pilot->rank_id); /** * Now go from ACCEPTED to REJECTED */ + $new_pirep_count = $pirep->pilot->flights - 1; + $new_flight_time = $pirep->pilot->flight_time - $pirep->flight_time; $this->pirepSvc->changeStatus($pirep, config('enums.pirep_status.REJECTED')); - $this->assertEquals(0, $pirep->pilot->flights); - $this->assertEquals(0, $pirep->pilot->flight_time); - $this->assertEquals(1, $pirep->pilot->rank_id); + $this->assertEquals($new_pirep_count, $pirep->pilot->flights); + $this->assertEquals($new_flight_time, $pirep->pilot->flight_time); + //$this->assertEquals(1, $pirep->pilot->rank_id); $this->assertEquals($pirep->arr_airport_id, $pirep->pilot->curr_airport_id); } @@ -93,30 +62,49 @@ class PIREPTest extends TestCase */ public function testPilotStatsIncr() { + $original_pilot = User::find(1); + # Submit two PIREPs - $pilot = $this->addPIREP(2); + $pireps = factory(Pirep::class, 2)->create([ + 'user_id' => 1, + # 360min == 6 hours, rank should bump up + 'flight_time' => 360, + ]); + + foreach ($pireps as $pirep) { + $this->pirepSvc->create($pirep); + $this->pirepSvc->accept($pirep); + } + + $pilot = User::find(1); $last_pirep = Pirep::where('id', $pilot->last_pirep_id)->first(); - $this->assertEquals(2, $pilot->flights); - $this->assertEquals(43200, $pilot->flight_time); - $this->assertEquals(2, $pilot->rank_id); + # Make sure rank went up + $this->assertGreaterThan($original_pilot->rank_id, $pilot->rank_id); $this->assertEquals($last_pirep->arr_airport_id, $pilot->curr_airport_id); # # Submit another PIREP, adding another 6 hours # it should automatically be accepted # - $pilot = $this->addPIREP(1, false); + $pirep = factory(Pirep::class)->create([ + 'user_id' => 1, + # 120min == 2 hours, currently at 9 hours + # Rank bumps up at 10 hours + 'flight_time' => 120, + ]); + + # Pilot should be at rank 2, where accept should be automatic + $this->pirepSvc->create($pirep); + + $pilot->refresh(); $latest_pirep = Pirep::where('id', $pilot->last_pirep_id)->first(); + # Make sure PIREP was auto updated + $this->assertEquals(config('enums.pirep_status.ACCEPTED'), $latest_pirep->status); + # Make sure latest PIREP was updated $this->assertNotEquals($last_pirep->id, $latest_pirep->id); - - # The PIREP should have been automatically accepted - $this->assertEquals( - config('enums.pirep_status.ACCEPTED'), - $latest_pirep->status - ); } public function testPirepFinances() diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 275d3d34..a7e13d52 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -26,16 +26,16 @@ class UtilsTest extends TestCase } public function testSecondsToTime() { - $t = Utils::secondsToTime(3600); + $t = Utils::secondsToTimeString(3600); $this->assertEquals('1h 0m', $t); - $t = Utils::secondsToTime(3720); + $t = Utils::secondsToTimeString(3720); $this->assertEquals('1h 2m', $t); - $t = Utils::secondsToTime(3722); + $t = Utils::secondsToTimeString(3722); $this->assertEquals('1h 2m', $t); - $t = Utils::secondsToTime(3722, true); + $t = Utils::secondsToTimeString(3722, true); $this->assertEquals('1h 2m 2s', $t); } } diff --git a/tests/data/base.yml b/tests/data/base.yml index 90860cc3..bffda52e 100644 --- a/tests/data/base.yml +++ b/tests/data/base.yml @@ -20,25 +20,12 @@ users: rank_id: 1 created_at: now updated_at: now - - id: 2 - name: Test User - email: test@phpvms.net - password: test - api_key: testuserapikey - airline_id: 1 - home_airport_id: KJFK - curr_airport_id: KJFK - rank_id: 1 - created_at: now - updated_at: now role_user: - user_id: 1 role_id: 1 - user_id: 1 role_id: 2 - - user_id: 2 - role_id: 2 ranks: - id: 1 @@ -58,39 +45,6 @@ ranks: auto_approve_manual: 1 auto_promote: 0 -airports: - - id: KAUS - icao: KAUS - name: Austin-Bergstrom - location: Austin, Texas, USA - lat: 30.1945278 - lon: -97.6698889 - fuel_jeta_cost: 100 - - id: KJFK - icao: KJFK - name: John F Kennedy - location: New York, New York, USA - lat: 40.6399257 - lon: -73.7786950 - fuel_jeta_cost: 50 - -aircraft: - - id: 1 - subfleet_id: 1 - name: Boeing 747-400 - registration: NC17 - tail_number: 17 - - id: 2 - subfleet_id: 2 - name: Boeing 777-200 - registration: NC20 - tail_number: 20 - - id: 3 - subfleet_id: 1 - name: Boeing 747-400-PW - registration: PW744 - tail_number: 207X - fares: - id: 1 code: Y @@ -108,20 +62,6 @@ fares: price: 800 capacity: 5 -subfleets: - - id: 1 - airline_id: 1 - name: 747-400 Winglets - type: 744W - fuel_type: 1 - fuel_capacity: 2000 - - id: 2 - airline_id: 1 - name: 777-200 LR - type: 772-LR - fuel_type: 1 - fuel_capacity: 1000 - # add a few mods to aircraft and fares subfleet_fare: @@ -148,11 +88,3 @@ subfleet_fare: subfleet_flight: - subfleet_id: 1 flight_id: 1 - -flights: - - id: 1 - airline_id: 1 - flight_number: 100 - dpt_airport_id: KAUS - arr_airport_id: KJFK - route: KAUS KJFK