audition = Audition::factory()->create(['minimum_grade' => 1, 'maximum_grade' => 14]); $this->entries = Entry::factory()->count(10)->create(['audition_id' => $this->audition->id]); $this->ranker = app(RankAuditionEntries::class); }); afterEach(function () { cache()->flush(); }); it('throws an exception if an invalid rank type is specified', function () { ($this->ranker)($this->audition, 'bababoey'); })->throws(AuditionAdminException::class, 'Invalid rank type (must be seating or advancement)'); // Test Rank for Seating it('ranks entries for seating if there are no ties', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 75, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); it('makes use of bonus scores when set', function () { $bonusScoreDefinition = BonusScoreDefinition::create([ 'name' => 'bonus', 'max_score' => 100, 'weight' => 1, 'for_seating' => 1, 'for_attendance' => 0, ]); $bonusScoreDefinition->auditions()->attach($this->audition); DB::table('bonus_scores')->insert([ 'entry_id' => $this->entries[2]->id, 'user_id' => 1, 'originally_scored_entry' => $this->entries[2]->id, 'score' => 100, 'created_at' => now(), 'updated_at' => now(), ]); // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score2 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 2, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], 'bonus_total' => 100, ]); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); it('assigns a seatingRank property to each entry that is scored', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 75, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->seatingRank)->toEqual(1) ->and($sortedEntries[1]->seatingRank)->toEqual(2) ->and($sortedEntries[2]->seatingRank)->toEqual(3) ->and($sortedEntries->count())->toEqual(3); }); it('skips a declined entry when assigning seatingRank properties', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 75, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); $this->entries[0]->addFlag('declined'); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->seatingRank)->toEqual(1) ->and($sortedEntries[1]->seatingRank)->toEqual('declined') ->and($sortedEntries[2]->seatingRank)->toEqual(2); }); it('uses the second subscore as a second tiebreaker for seating', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 50, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 4], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 50, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 6], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); it('uses the first subscore as a tiebreaker for seating', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 50, 'advancement_total' => 75, 'seating_subscore_totals' => [4, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 50, 'advancement_total' => 25, 'seating_subscore_totals' => [6, 5], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'seating'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); // Test Rank for Advancement it('ranks entries for advancement if there are no ties', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 75, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'advancement'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); it('assigns a advancementRank property to each entry that is scored', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 75, 'advancement_total' => 25, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 25, 'advancement_total' => 75, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'advancement'); expect($sortedEntries[0]->advancementRank)->toEqual(1) ->and($sortedEntries[1]->advancementRank)->toEqual(2) ->and($sortedEntries[2]->advancementRank)->toEqual(3) ->and($sortedEntries->count())->toEqual(3); }); it('uses the second subscore as a second tiebreaker for advancement', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 75, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 4], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 25, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 6], ]); $sortedEntries = ($this->ranker)($this->audition, 'advancement'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); }); it('uses the first subscore as a tiebreaker for advancement', function () { // entry 0 will be second place $score0 = EntryTotalScore::create([ 'entry_id' => $this->entries[0]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [5, 5], ]); // entry 1 will be third place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[1]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [4, 5], ]); // entry 2 will be first place $score1 = EntryTotalScore::create([ 'entry_id' => $this->entries[2]->id, 'seating_total' => 50, 'advancement_total' => 50, 'seating_subscore_totals' => [5, 5], 'advancement_subscore_totals' => [6, 5], ]); $sortedEntries = ($this->ranker)($this->audition, 'advancement'); expect($sortedEntries[0]->id)->toEqual($this->entries[2]->id) ->and($sortedEntries[1]->id)->toEqual($this->entries[0]->id) ->and($sortedEntries[2]->id)->toEqual($this->entries[1]->id); });