Create tests for app/actions/tabulation/TotalEntryScore
This commit is contained in:
parent
53ccc5a7a3
commit
c67c1ad79c
|
|
@ -19,7 +19,6 @@ class TotalEntryScores
|
||||||
|
|
||||||
public function __invoke(Entry $entry, bool $force_recalculation = false): void
|
public function __invoke(Entry $entry, bool $force_recalculation = false): void
|
||||||
{
|
{
|
||||||
// TODO Verify accuracy of calculations, particularly for olympic scoring
|
|
||||||
if ($force_recalculation) {
|
if ($force_recalculation) {
|
||||||
EntryTotalScore::where('entry_id', $entry->id)->delete();
|
EntryTotalScore::where('entry_id', $entry->id)->delete();
|
||||||
}
|
}
|
||||||
|
|
@ -34,17 +33,19 @@ class TotalEntryScores
|
||||||
// deal with seating scores
|
// deal with seating scores
|
||||||
// TODO: Consider a rewrite to pull the scoreSheets from the entry model so they may be preloaded
|
// TODO: Consider a rewrite to pull the scoreSheets from the entry model so they may be preloaded
|
||||||
$scoreSheets = ScoreSheet::where('entry_id', $entry->id)->orderBy('seating_total', 'desc')->get();
|
$scoreSheets = ScoreSheet::where('entry_id', $entry->id)->orderBy('seating_total', 'desc')->get();
|
||||||
|
|
||||||
// bail out if there are not enough score sheets
|
// bail out if there are not enough score sheets
|
||||||
$assignedJudges = $entry->audition->judges()->count();
|
$assignedJudges = $entry->audition->judges()->count();
|
||||||
if ($scoreSheets->count() == 0 || $scoreSheets->count() < $assignedJudges) {
|
if ($scoreSheets->count() == 0 || $scoreSheets->count() < $assignedJudges) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (auditionSetting('olympic_scoring' && $scoreSheets->count() > 2)) {
|
|
||||||
|
if (auditionSetting('olympic_scoring') && $scoreSheets->count() > 2) {
|
||||||
// under olympic scoring, drop the first and last element
|
// under olympic scoring, drop the first and last element
|
||||||
$scoreSheets->shift();
|
$scoreSheets->shift();
|
||||||
$scoreSheets->pop();
|
$scoreSheets->pop();
|
||||||
}
|
}
|
||||||
$newTotaledScore->seating_total = $scoreSheets->avg('seating_total');
|
$newTotaledScore->seating_total = round($scoreSheets->avg('seating_total'), 6);
|
||||||
$seatingSubscores = $requiredSubscores
|
$seatingSubscores = $requiredSubscores
|
||||||
->filter(fn ($subscore) => $subscore->for_seating == true)
|
->filter(fn ($subscore) => $subscore->for_seating == true)
|
||||||
->sortBy('tiebreak_order');
|
->sortBy('tiebreak_order');
|
||||||
|
|
@ -54,18 +55,18 @@ class TotalEntryScores
|
||||||
foreach ($scoreSheets as $scoreSheet) {
|
foreach ($scoreSheets as $scoreSheet) {
|
||||||
$runningTotal += $scoreSheet->subscores[$subscore->id]['score'];
|
$runningTotal += $scoreSheet->subscores[$subscore->id]['score'];
|
||||||
}
|
}
|
||||||
$total_seating_subscores[] = $runningTotal / $scoreSheets->count();
|
$total_seating_subscores[] = round($runningTotal / $scoreSheets->count(), 4);
|
||||||
}
|
}
|
||||||
$newTotaledScore->seating_subscore_totals = $total_seating_subscores;
|
$newTotaledScore->seating_subscore_totals = $total_seating_subscores;
|
||||||
|
|
||||||
// deal with advancement scores
|
// deal with advancement scores
|
||||||
$scoreSheets = ScoreSheet::where('entry_id', $entry->id)->orderBy('advancement_total', 'desc')->get();
|
$scoreSheets = ScoreSheet::where('entry_id', $entry->id)->orderBy('advancement_total', 'desc')->get();
|
||||||
if (auditionSetting('olympic_scoring' && $scoreSheets->count() > 2)) {
|
if (auditionSetting('olympic_scoring') && $scoreSheets->count() > 2) {
|
||||||
// under olympic scoring, drop the first and last element
|
// under olympic scoring, drop the first and last element
|
||||||
$scoreSheets->shift();
|
$scoreSheets->shift();
|
||||||
$scoreSheets->pop();
|
$scoreSheets->pop();
|
||||||
}
|
}
|
||||||
$newTotaledScore->advancement_total = $scoreSheets->avg('advancement_total');
|
$newTotaledScore->advancement_total = round($scoreSheets->avg('advancement_total'), 6);
|
||||||
$advancement_subscores = $requiredSubscores
|
$advancement_subscores = $requiredSubscores
|
||||||
->filter(fn ($subscore) => $subscore->for_advance == true)
|
->filter(fn ($subscore) => $subscore->for_advance == true)
|
||||||
->sortBy('tiebreak_order');
|
->sortBy('tiebreak_order');
|
||||||
|
|
@ -75,7 +76,7 @@ class TotalEntryScores
|
||||||
foreach ($scoreSheets as $scoreSheet) {
|
foreach ($scoreSheets as $scoreSheet) {
|
||||||
$runningTotal += $scoreSheet->subscores[$subscore->id]['score'];
|
$runningTotal += $scoreSheet->subscores[$subscore->id]['score'];
|
||||||
}
|
}
|
||||||
$total_advancement_subscores[] = $runningTotal / $scoreSheets->count();
|
$total_advancement_subscores[] = round($runningTotal / $scoreSheets->count(), 4);
|
||||||
}
|
}
|
||||||
$newTotaledScore->advancement_subscore_totals = $total_advancement_subscores;
|
$newTotaledScore->advancement_subscore_totals = $total_advancement_subscores;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,206 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
|
||||||
|
use App\Actions\Tabulation\EnterScore;
|
||||||
|
use App\Actions\Tabulation\TotalEntryScores;
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\BonusScore;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\EntryTotalScore;
|
||||||
|
use App\Models\ScoreSheet;
|
||||||
|
use App\Models\SubscoreDefinition;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Settings;
|
||||||
|
use Database\Seeders\AuditionWithScoringGuideAndRoom;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
(new AuditionWithScoringGuideAndRoom)->run();
|
||||||
|
SubscoreDefinition::where('id', '<', 900)->delete();
|
||||||
|
$this->audition = Audition::first();
|
||||||
|
$this->judge1 = User::factory()->create();
|
||||||
|
$this->judge2 = User::factory()->create();
|
||||||
|
$this->judge3 = User::factory()->create();
|
||||||
|
$this->judge4 = User::factory()->create();
|
||||||
|
$this->judge5 = User::factory()->create();
|
||||||
|
$this->audition->judges()->attach([
|
||||||
|
$this->judge1->id,
|
||||||
|
$this->judge2->id,
|
||||||
|
$this->judge3->id,
|
||||||
|
$this->judge4->id,
|
||||||
|
$this->judge5->id,
|
||||||
|
]);
|
||||||
|
$this->entry = Entry::factory()->create(['audition_id' => $this->audition->id]);
|
||||||
|
$this->judge1Subscores = [
|
||||||
|
1001 => 45,
|
||||||
|
1002 => 87,
|
||||||
|
1003 => 34,
|
||||||
|
1004 => 86,
|
||||||
|
1005 => 75,
|
||||||
|
];
|
||||||
|
$this->judge2Subscores = [
|
||||||
|
1001 => 75,
|
||||||
|
1002 => 69,
|
||||||
|
1003 => 56,
|
||||||
|
1004 => 89,
|
||||||
|
1005 => 45,
|
||||||
|
];
|
||||||
|
$this->judge3Subscores = [
|
||||||
|
1001 => 78,
|
||||||
|
1002 => 56,
|
||||||
|
1003 => 98,
|
||||||
|
1004 => 34,
|
||||||
|
1005 => 56,
|
||||||
|
];
|
||||||
|
$this->judge4Subscores = [
|
||||||
|
1001 => 67,
|
||||||
|
1002 => 45,
|
||||||
|
1003 => 98,
|
||||||
|
1004 => 43,
|
||||||
|
1005 => 89,
|
||||||
|
];
|
||||||
|
$this->judge5Subscores = [
|
||||||
|
1001 => 45,
|
||||||
|
1002 => 97,
|
||||||
|
1003 => 34,
|
||||||
|
1004 => 97,
|
||||||
|
1005 => 78,
|
||||||
|
];
|
||||||
|
$this->scribe = app(EnterScore::class);
|
||||||
|
$this->calculator = app(TotalEntryScores::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('scores correctly for non-olympic scoring', function () {
|
||||||
|
Settings::set('olympic_scoring', false);
|
||||||
|
($this->scribe)($this->judge1, $this->entry, $this->judge1Subscores);
|
||||||
|
($this->scribe)($this->judge2, $this->entry, $this->judge2Subscores);
|
||||||
|
($this->scribe)($this->judge3, $this->entry, $this->judge3Subscores);
|
||||||
|
($this->scribe)($this->judge4, $this->entry, $this->judge4Subscores);
|
||||||
|
($this->scribe)($this->judge5, $this->entry, $this->judge5Subscores);
|
||||||
|
$judges = [
|
||||||
|
$this->judge1,
|
||||||
|
$this->judge2,
|
||||||
|
$this->judge3,
|
||||||
|
$this->judge4,
|
||||||
|
$this->judge5,
|
||||||
|
];
|
||||||
|
$expectedSeatingTotals = [
|
||||||
|
1 => 68.125,
|
||||||
|
2 => 74,
|
||||||
|
3 => 61,
|
||||||
|
4 => 60.25,
|
||||||
|
5 => 74.75,
|
||||||
|
];
|
||||||
|
$expectedAdvancementTotals = [
|
||||||
|
1 => 71.875,
|
||||||
|
2 => 70.25,
|
||||||
|
3 => 58.25,
|
||||||
|
4 => 63,
|
||||||
|
5 => 78.875,
|
||||||
|
];
|
||||||
|
foreach ($judges as $judge) {
|
||||||
|
$scoreSheet = ScoreSheet::where('entry_id', $this->entry->id)->where('user_id', $judge->id)->first();
|
||||||
|
expect($scoreSheet->seating_total)->toBe($expectedSeatingTotals[$judge->id])
|
||||||
|
->and($scoreSheet->advancement_total)->toBe($expectedAdvancementTotals[$judge->id]);
|
||||||
|
}
|
||||||
|
($this->calculator)($this->entry);
|
||||||
|
$totalScore = EntryTotalScore::where('entry_id', $this->entry->id)->first();
|
||||||
|
expect($totalScore->seating_subscore_totals)->toBe([69.8, 70.8, 64, 62])
|
||||||
|
->and($totalScore->advancement_subscore_totals)->toBe([68.6, 69.8, 70.8, 64])
|
||||||
|
->and($totalScore->seating_total)->toBe(67.625)
|
||||||
|
->and($totalScore->advancement_total)->toBe(68.45);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('scores correctly for olympic scoring', function () {
|
||||||
|
Settings::set('olympic_scoring', true);
|
||||||
|
($this->scribe)($this->judge1, $this->entry, $this->judge1Subscores);
|
||||||
|
($this->scribe)($this->judge2, $this->entry, $this->judge2Subscores);
|
||||||
|
($this->scribe)($this->judge3, $this->entry, $this->judge3Subscores);
|
||||||
|
($this->scribe)($this->judge4, $this->entry, $this->judge4Subscores);
|
||||||
|
($this->scribe)($this->judge5, $this->entry, $this->judge5Subscores);
|
||||||
|
$judges = [
|
||||||
|
$this->judge1,
|
||||||
|
$this->judge2,
|
||||||
|
$this->judge3,
|
||||||
|
$this->judge4,
|
||||||
|
$this->judge5,
|
||||||
|
];
|
||||||
|
$expectedSeatingTotals = [
|
||||||
|
1 => 68.125,
|
||||||
|
2 => 74,
|
||||||
|
3 => 61,
|
||||||
|
4 => 60.25,
|
||||||
|
5 => 74.75,
|
||||||
|
];
|
||||||
|
$expectedAdvancementTotals = [
|
||||||
|
1 => 71.875,
|
||||||
|
2 => 70.25,
|
||||||
|
3 => 58.25,
|
||||||
|
4 => 63,
|
||||||
|
5 => 78.875,
|
||||||
|
];
|
||||||
|
foreach ($judges as $judge) {
|
||||||
|
$scoreSheet = ScoreSheet::where('entry_id', $this->entry->id)->where('user_id', $judge->id)->first();
|
||||||
|
expect($scoreSheet->seating_total)->toBe($expectedSeatingTotals[$judge->id])
|
||||||
|
->and($scoreSheet->advancement_total)->toBe($expectedAdvancementTotals[$judge->id]);
|
||||||
|
}
|
||||||
|
($this->calculator)($this->entry);
|
||||||
|
$totalScore = EntryTotalScore::where('entry_id', $this->entry->id)->first();
|
||||||
|
expect($totalScore->seating_subscore_totals)->toBe([69.6667, 70.6667, 62.6667, 66])
|
||||||
|
->and($totalScore->advancement_subscore_totals)->toBe([69.6667, 72.6667, 67, 62.6667])
|
||||||
|
->and($totalScore->seating_total)->toBe(67.708333)
|
||||||
|
->and($totalScore->advancement_total)->toBe(68.375);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it correctly brings in bonus scores', function () {
|
||||||
|
Settings::set('olympic_scoring', false);
|
||||||
|
($this->scribe)($this->judge1, $this->entry, $this->judge1Subscores);
|
||||||
|
($this->scribe)($this->judge2, $this->entry, $this->judge2Subscores);
|
||||||
|
($this->scribe)($this->judge3, $this->entry, $this->judge3Subscores);
|
||||||
|
($this->scribe)($this->judge4, $this->entry, $this->judge4Subscores);
|
||||||
|
($this->scribe)($this->judge5, $this->entry, $this->judge5Subscores);
|
||||||
|
$judges = [
|
||||||
|
$this->judge1,
|
||||||
|
$this->judge2,
|
||||||
|
$this->judge3,
|
||||||
|
$this->judge4,
|
||||||
|
$this->judge5,
|
||||||
|
];
|
||||||
|
$expectedSeatingTotals = [
|
||||||
|
1 => 68.125,
|
||||||
|
2 => 74,
|
||||||
|
3 => 61,
|
||||||
|
4 => 60.25,
|
||||||
|
5 => 74.75,
|
||||||
|
];
|
||||||
|
$expectedAdvancementTotals = [
|
||||||
|
1 => 71.875,
|
||||||
|
2 => 70.25,
|
||||||
|
3 => 58.25,
|
||||||
|
4 => 63,
|
||||||
|
5 => 78.875,
|
||||||
|
];
|
||||||
|
foreach ($judges as $judge) {
|
||||||
|
$scoreSheet = ScoreSheet::where('entry_id', $this->entry->id)->where('user_id', $judge->id)->first();
|
||||||
|
expect($scoreSheet->seating_total)->toBe($expectedSeatingTotals[$judge->id])
|
||||||
|
->and($scoreSheet->advancement_total)->toBe($expectedAdvancementTotals[$judge->id]);
|
||||||
|
}
|
||||||
|
$bonusScore = BonusScore::create([
|
||||||
|
'entry_id' => $this->entry->id,
|
||||||
|
'user_id' => $this->judge1,
|
||||||
|
'originally_scored_entry' => $this->entry->id,
|
||||||
|
'score' => 6,
|
||||||
|
]);
|
||||||
|
($this->calculator)($this->entry);
|
||||||
|
$totalScore = EntryTotalScore::where('entry_id', $this->entry->id)->first();
|
||||||
|
|
||||||
|
expect($totalScore->seating_subscore_totals)->toBe([69.8, 70.8, 64, 62])
|
||||||
|
->and($totalScore->advancement_subscore_totals)->toBe([68.6, 69.8, 70.8, 64])
|
||||||
|
->and($totalScore->seating_total)->toBe(67.625)
|
||||||
|
->and($totalScore->advancement_total)->toBe(68.45)
|
||||||
|
->and($totalScore->bonus_total)->toBe(6)
|
||||||
|
->and($totalScore->seating_total_with_bonus)->toBe(73.625);
|
||||||
|
});
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Settings;
|
use App\Settings;
|
||||||
use Illuminate\Foundation\Testing\TestCase;
|
|
||||||
use function Pest\Laravel\actingAs;
|
use function Pest\Laravel\actingAs;
|
||||||
use function Pest\Laravel\artisan;
|
use function Pest\Laravel\artisan;
|
||||||
|
|
||||||
|
|
@ -80,5 +80,5 @@ uses()->beforeEach(function () {
|
||||||
Settings::set('payment_city', 'Washington');
|
Settings::set('payment_city', 'Washington');
|
||||||
Settings::set('payment_state', 'DC');
|
Settings::set('payment_state', 'DC');
|
||||||
Settings::set('payment_zip', '20500');
|
Settings::set('payment_zip', '20500');
|
||||||
|
Settings::set('olympic_scoring', 1);
|
||||||
})->in('Feature');
|
})->in('Feature');
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue