361 lines
13 KiB
PHP
361 lines
13 KiB
PHP
<?php
|
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */
|
|
|
|
use App\Actions\Tabulation\RankAuditionEntries;
|
|
use App\Exceptions\AuditionAdminException;
|
|
use App\Models\Audition;
|
|
use App\Models\BonusScoreDefinition;
|
|
use App\Models\Entry;
|
|
use App\Models\EntryTotalScore;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->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);
|
|
});
|