Rewrite tabulation #14
|
|
@ -1,13 +1,67 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
|
||||||
namespace App\Actions\Tabulation;
|
namespace App\Actions\Tabulation;
|
||||||
|
|
||||||
|
use App\Exceptions\TabulationException;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
|
|
||||||
class AllJudgesCount implements CalculateEntryScore
|
class AllJudgesCount implements CalculateEntryScore
|
||||||
{
|
{
|
||||||
|
protected CalculateScoreSheetTotal $calculator;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->calculator = new CalculateScoreSheetTotal();
|
||||||
|
}
|
||||||
|
|
||||||
public function calculate(string $mode, Entry $entry): array
|
public function calculate(string $mode, Entry $entry): array
|
||||||
{
|
{
|
||||||
return ['vinita'=>'hornets'];
|
$this->basicValidation($mode, $entry);
|
||||||
|
$this->areAllJudgesIn($entry);
|
||||||
|
$this->areAllJudgesValid($entry);
|
||||||
|
return $this->getJudgeTotals($mode, $entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getJudgeTotals($mode, Entry $entry)
|
||||||
|
{
|
||||||
|
$scores = [];
|
||||||
|
foreach ($entry->audition->judges as $judge) {
|
||||||
|
$scores[] = $this->calculator->__invoke($mode, $entry, $judge);
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < count($scores[0]); $i++) {
|
||||||
|
$sums[] = $scores[0][$i] + $scores[1][$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sums;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function basicValidation($mode, $entry): void
|
||||||
|
{
|
||||||
|
if ($mode !== 'seating' && $mode !== 'advancement') {
|
||||||
|
throw new TabulationException('Mode must be seating or advancement');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $entry->exists()) {
|
||||||
|
throw new TabulationException('Invalid entry specified');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function areAllJudgesIn(Entry $entry): void
|
||||||
|
{
|
||||||
|
$assignedJudgeCount = $entry->audition->judges->count();
|
||||||
|
if ($entry->scoreSheets->count() !== $assignedJudgeCount) {
|
||||||
|
throw new TabulationException('Not all score sheets are in');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function areAllJudgesValid(Entry $entry): void
|
||||||
|
{
|
||||||
|
$validJudgeIds = $entry->audition->judges->pluck('id')->sort()->toArray();
|
||||||
|
$existingJudgeIds = $entry->scoreSheets->pluck('user_id')->sort()->toArray();
|
||||||
|
if ($validJudgeIds !== $existingJudgeIds) {
|
||||||
|
throw new TabulationException('Score exists from a judge not assigned to this audition');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Actions\Tabulation\CalculateEntryScore;
|
use App\Actions\Tabulation\CalculateEntryScore;
|
||||||
|
use App\Exceptions\TabulationException;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
|
|
||||||
class TestController extends Controller
|
class TestController extends Controller
|
||||||
|
|
@ -15,8 +16,29 @@ class TestController extends Controller
|
||||||
|
|
||||||
public function flashTest()
|
public function flashTest()
|
||||||
{
|
{
|
||||||
$test = $this->bigCalc->calculate('seating', Entry::find(1127))['vinita'];
|
$entries = Entry::forSeating()->with('student')->where('audition_id', 19)->get();
|
||||||
|
$rows = [];
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
try {
|
||||||
|
$totalScore = $this->bigCalc->calculate('seating', $entry)[0];
|
||||||
|
} catch (TabulationException $ex){
|
||||||
|
$totalScore = '--';
|
||||||
|
}
|
||||||
|
$rows[] = [
|
||||||
|
'name' => $entry->student->full_name(),
|
||||||
|
'totalScore' => $totalScore,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return view('test', compact('test'));
|
// try {
|
||||||
|
// $test = $this->bigCalc->calculate('seating', Entry::find(1061))[0];
|
||||||
|
// } catch (TabulationException $ex) {
|
||||||
|
// dd($ex);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return view('test', compact('rows'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Providers;
|
||||||
|
|
||||||
use App\Actions\Tabulation\AllJudgesCount;
|
use App\Actions\Tabulation\AllJudgesCount;
|
||||||
use App\Actions\Tabulation\CalculateEntryScore;
|
use App\Actions\Tabulation\CalculateEntryScore;
|
||||||
|
use App\Actions\Tabulation\CalculateScoreSheetTotal;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class CalculateEntryScoreProvider extends ServiceProvider
|
class CalculateEntryScoreProvider extends ServiceProvider
|
||||||
|
|
@ -13,6 +14,7 @@ class CalculateEntryScoreProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
|
$this->app->singleton(CalculateScoreSheetTotal::class, CalculateScoreSheetTotal::class);
|
||||||
$this->app->singleton(CalculateEntryScore::class, AllJudgesCount::class);
|
$this->app->singleton(CalculateEntryScore::class, AllJudgesCount::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,8 @@
|
||||||
@inject('drawService', 'App\Services\DrawService')
|
@inject('drawService', 'App\Services\DrawService')
|
||||||
<x-layout.app>
|
<x-layout.app>
|
||||||
<x-slot:page_title>Test Page</x-slot:page_title>
|
<x-slot:page_title>Test Page</x-slot:page_title>
|
||||||
@php
|
@foreach($rows as $row)
|
||||||
|
{{ $row['name'] }} - {{ $row['totalScore'] }}<hr>
|
||||||
@endphp
|
@endforeach
|
||||||
Test value: {{ $test }}
|
|
||||||
|
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
|
||||||
|
use App\Actions\Tabulation\AllJudgesCount;
|
||||||
|
use App\Exceptions\TabulationException;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Room;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('throws an exception if mode is not seating or advancement', function () {
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
$calculator->calculate('WRONG', Entry::factory()->create());
|
||||||
|
})->throws(TabulationException::class, 'Mode must be seating or advancement');
|
||||||
|
|
||||||
|
it('throws an exception if entry is not valid', function () {
|
||||||
|
// Arrange
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
// Act
|
||||||
|
$calculator->calculate('seating', Entry::factory()->make());
|
||||||
|
// Assert
|
||||||
|
})->throws(TabulationException::class, 'Invalid entry specified');
|
||||||
|
it('throws an exception if entry is missing judge scores', function () {
|
||||||
|
// Arrange
|
||||||
|
loadSampleAudition();
|
||||||
|
$judge1 = User::factory()->create();
|
||||||
|
$judge2 = User::factory()->create();
|
||||||
|
Room::find(1000)->addJudge($judge1);
|
||||||
|
Room::find(1000)->addJudge($judge2);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||||
|
$scores = [
|
||||||
|
1001 => 50,
|
||||||
|
1002 => 60,
|
||||||
|
1003 => 70,
|
||||||
|
1004 => 80,
|
||||||
|
1005 => 90,
|
||||||
|
];
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
enterScore($judge1, $entry, $scores);
|
||||||
|
// Act
|
||||||
|
$calculator->calculate('seating', $entry);
|
||||||
|
// Assert
|
||||||
|
})->throws(TabulationException::class, 'Not all score sheets are in');
|
||||||
|
|
||||||
|
it('throws an exception if a score exists from an invalid judge', function () {
|
||||||
|
// Arrange
|
||||||
|
loadSampleAudition();
|
||||||
|
$judge1 = User::factory()->create();
|
||||||
|
$judge2 = User::factory()->create();
|
||||||
|
$judge3 = User::factory()->create();
|
||||||
|
Room::find(1000)->addJudge($judge1);
|
||||||
|
Room::find(1000)->addJudge($judge2);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||||
|
$scores = [
|
||||||
|
1001 => 50,
|
||||||
|
1002 => 60,
|
||||||
|
1003 => 70,
|
||||||
|
1004 => 80,
|
||||||
|
1005 => 90,
|
||||||
|
];
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
enterScore($judge1, $entry, $scores);
|
||||||
|
$scoreSheetToSpoof = enterScore($judge2, $entry, $scores);
|
||||||
|
$scoreSheetToSpoof->update(['user_id' => $judge3->id]);
|
||||||
|
// Act
|
||||||
|
$calculator->calculate('seating', $entry);
|
||||||
|
// Assert
|
||||||
|
})->throws(TabulationException::class, 'Score exists from a judge not assigned to this audition');
|
||||||
|
|
||||||
|
it('correctly calculates scores for seating', function () {
|
||||||
|
// Arrange
|
||||||
|
loadSampleAudition();
|
||||||
|
$judge1 = User::factory()->create();
|
||||||
|
$judge2 = User::factory()->create();
|
||||||
|
Room::find(1000)->addJudge($judge1);
|
||||||
|
Room::find(1000)->addJudge($judge2);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||||
|
$scores = [
|
||||||
|
1001 => 50,
|
||||||
|
1002 => 60,
|
||||||
|
1003 => 70,
|
||||||
|
1004 => 80,
|
||||||
|
1005 => 90,
|
||||||
|
];
|
||||||
|
$scores2 = [
|
||||||
|
1001 => 55,
|
||||||
|
1002 => 65,
|
||||||
|
1003 => 75,
|
||||||
|
1004 => 85,
|
||||||
|
1005 => 95,
|
||||||
|
];
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
enterScore($judge1, $entry, $scores);
|
||||||
|
enterScore($judge2, $entry, $scores2);
|
||||||
|
// Act
|
||||||
|
$finalScores = $calculator->calculate('seating', $entry);
|
||||||
|
// Assert
|
||||||
|
$expectedScores = [142.5, 165, 125, 145, 105];
|
||||||
|
expect($finalScores)->toBe($expectedScores);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('correctly calculates scores for advancement', function () {
|
||||||
|
// Arrange
|
||||||
|
loadSampleAudition();
|
||||||
|
$judge1 = User::factory()->create();
|
||||||
|
$judge2 = User::factory()->create();
|
||||||
|
Room::find(1000)->addJudge($judge1);
|
||||||
|
Room::find(1000)->addJudge($judge2);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||||
|
$scores = [
|
||||||
|
1001 => 50,
|
||||||
|
1002 => 60,
|
||||||
|
1003 => 70,
|
||||||
|
1004 => 80,
|
||||||
|
1005 => 90,
|
||||||
|
];
|
||||||
|
$scores2 = [
|
||||||
|
1001 => 55,
|
||||||
|
1002 => 65,
|
||||||
|
1003 => 75,
|
||||||
|
1004 => 85,
|
||||||
|
1005 => 95,
|
||||||
|
];
|
||||||
|
$calculator = new AllJudgesCount();
|
||||||
|
enterScore($judge1, $entry, $scores);
|
||||||
|
enterScore($judge2, $entry, $scores2);
|
||||||
|
// Act
|
||||||
|
$finalScores = $calculator->calculate('advancement', $entry);
|
||||||
|
// Assert
|
||||||
|
$expectedScores = [152.5, 185, 165, 125, 145];
|
||||||
|
expect($finalScores)->toBe($expectedScores);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue