Rewrite tabulation #14
|
|
@ -13,7 +13,8 @@ class AllJudgesCount implements CalculateEntryScore
|
|||
|
||||
public function __construct()
|
||||
{
|
||||
$this->calculator = new CalculateScoreSheetTotal();
|
||||
#$this->calculator = new CalculateScoreSheetTotal();
|
||||
$this->calculator = app(CalculateScoreSheetTotal::class);
|
||||
}
|
||||
|
||||
public function calculate(string $mode, Entry $entry): array
|
||||
|
|
@ -31,6 +32,7 @@ class AllJudgesCount implements CalculateEntryScore
|
|||
foreach ($entry->audition->judges as $judge) {
|
||||
$scores[] = $this->calculator->__invoke($mode, $entry, $judge);
|
||||
}
|
||||
$sums = [];
|
||||
// Sum each subscore from the judges
|
||||
foreach ($scores as $score) {
|
||||
$index = 0;
|
||||
|
|
|
|||
|
|
@ -5,14 +5,18 @@
|
|||
namespace App\Actions\Tabulation;
|
||||
|
||||
use App\Exceptions\TabulationException;
|
||||
use App\Models\Audition;
|
||||
use App\Models\Entry;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\User;
|
||||
use App\Services\AuditionService;
|
||||
|
||||
class CalculateScoreSheetTotal
|
||||
{
|
||||
public function __construct()
|
||||
protected AuditionService $auditionService;
|
||||
public function __construct(AuditionService $auditionService)
|
||||
{
|
||||
$this->auditionService = $auditionService;
|
||||
}
|
||||
|
||||
public function __invoke(string $mode, Entry $entry, User $judge): array
|
||||
|
|
@ -22,10 +26,8 @@ class CalculateScoreSheetTotal
|
|||
if (! $scoreSheet) {
|
||||
throw new TabulationException('No score sheet by that judge for that entry');
|
||||
}
|
||||
$subscores = match ($mode) {
|
||||
'seating' => $entry->audition->scoringGuide->subscores->where('for_seating', true)->sortBy('tiebreak_order'),
|
||||
'advancement' => $entry->audition->scoringGuide->subscores->where('for_advance', true)->sortBy('tiebreak_order'),
|
||||
};
|
||||
#$subscores = $this->getSubscores($mode, $entry->audition);
|
||||
$subscores = $this->auditionService->getSubscores($entry->audition, $mode);
|
||||
$scoreTotal = 0;
|
||||
$weightsTotal = 0;
|
||||
$scoreArray = [];
|
||||
|
|
@ -39,6 +41,7 @@ class CalculateScoreSheetTotal
|
|||
$finalScore = $scoreTotal / $weightsTotal;
|
||||
// put $final score at the beginning of the $ScoreArray
|
||||
array_unshift($scoreArray, $finalScore);
|
||||
|
||||
return $scoreArray;
|
||||
}
|
||||
|
||||
|
|
@ -54,4 +57,29 @@ class CalculateScoreSheetTotal
|
|||
throw new TabulationException('Invalid judge provided');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSubscores($mode, Audition $audition)
|
||||
{
|
||||
static $seatingSubscores = [];
|
||||
static $advancementSubscores = [];
|
||||
|
||||
if ($mode === 'seating') {
|
||||
if (! isset($seatingSubscores[$audition->id])) {
|
||||
$seatingSubscores[$audition->id] = $audition->scoringGuide->subscores->where('for_seating',
|
||||
true)->sortBy('tiebreak_order');
|
||||
}
|
||||
|
||||
return $seatingSubscores[$audition->id];
|
||||
}
|
||||
if ($mode === 'advancement') {
|
||||
if (! isset($advancementSubscores[$audition->id])) {
|
||||
$advancementSubscores[$audition->id] = $audition->scoringGuide->subscores->where('for_advance',
|
||||
true)->sortBy('tiebreak_order');
|
||||
}
|
||||
|
||||
return $advancementSubscores[$audition->id];
|
||||
}
|
||||
|
||||
throw new TabulationException('Invalid mode requested. Mode must be seating or advancement');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class AuditionServiceException extends Exception
|
||||
{
|
||||
//
|
||||
}
|
||||
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Actions\Tabulation\AllJudgesCount;
|
||||
use App\Actions\Tabulation\CalculateEntryScore;
|
||||
use App\Actions\Tabulation\CalculateScoreSheetTotal;
|
||||
use App\Models\Audition;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Room;
|
||||
|
|
@ -47,9 +44,9 @@ class AppServiceProvider extends ServiceProvider
|
|||
return new DrawService();
|
||||
});
|
||||
//
|
||||
// $this->app->singleton(AuditionService::class, function () {
|
||||
// return new AuditionService();
|
||||
// });
|
||||
$this->app->singleton(AuditionService::class, function () {
|
||||
return new AuditionService();
|
||||
});
|
||||
//
|
||||
// $this->app->singleton(SeatingService::class, function ($app) {
|
||||
// return new SeatingService($app->make(TabulationService::class));
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Exceptions\AuditionServiceException;
|
||||
use App\Models\Audition;
|
||||
use App\Models\ScoringGuide;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AuditionService
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a new class instance.
|
||||
*/
|
||||
|
|
@ -18,5 +16,51 @@ class AuditionService
|
|||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AuditionServiceException
|
||||
*/
|
||||
public function getSubscores(Audition $audition, $mode = 'seating', $sort = 'tiebreak')
|
||||
{
|
||||
static $auditionSubscores = [];
|
||||
$this->validateAudition($audition);
|
||||
$this->validateMode($mode);
|
||||
$this->validateSort($sort);
|
||||
|
||||
$sortColumn = match ($sort) {
|
||||
'tiebreak' => 'tiebreak_order',
|
||||
'display' => 'display_order',
|
||||
};
|
||||
$modeColumn = match ($mode) {
|
||||
'seating' => 'for_seating',
|
||||
'advancement' => 'for_advance',
|
||||
};
|
||||
if (! isset($auditionSubscores[$mode][$sort])) {
|
||||
$auditionSubscores[$mode][$sort] = $audition->scoringGuide->subscores->where($modeColumn, true)->sortBy($sortColumn);
|
||||
} else {
|
||||
Log::debug('Using cached subscores');
|
||||
}
|
||||
|
||||
return $auditionSubscores[$mode][$sort];
|
||||
}
|
||||
|
||||
protected function validateAudition($audition)
|
||||
{
|
||||
if (! $audition->exists()) {
|
||||
throw new AuditionServiceException('Invalid audition provided');
|
||||
}
|
||||
}
|
||||
|
||||
protected function validateMode($mode)
|
||||
{
|
||||
if ($mode !== 'seating' && $mode !== 'advancement') {
|
||||
throw new AuditionServiceException('Invalid mode requested. Mode must be seating or advancement');
|
||||
}
|
||||
}
|
||||
|
||||
protected function validateSort($sort)
|
||||
{
|
||||
if ($sort !== 'tiebreak' && $sort !== 'display') {
|
||||
throw new AuditionServiceException('Invalid sort requested. Sort must be tiebreak or weight');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,23 +11,23 @@ use Illuminate\Foundation\Testing\RefreshDatabase;
|
|||
|
||||
uses(RefreshDatabase::class);
|
||||
beforeEach(function () {
|
||||
$this->calculator = new CalculateScoreSheetTotal();
|
||||
$this->calculator = app(CalculateScoreSheetTotal::class);
|
||||
});
|
||||
it('throws an exception if an invalid mode is called for', function () {
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
$calculator('anything', Entry::factory()->create(), User::factory()->create());
|
||||
})->throws(TabulationException::class, 'Invalid mode requested. Mode must be seating or advancement');
|
||||
it('throws an exception if an invalid judge is provided', function () {
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
$calculator('seating', Entry::factory()->create(), User::factory()->make());
|
||||
})->throws(TabulationException::class, 'Invalid judge provided');
|
||||
it('throws an exception if an invalid entry is provided', function () {
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
$calculator('advancement', Entry::factory()->make(), User::factory()->create());
|
||||
})->throws(TabulationException::class, 'Invalid entry provided');
|
||||
it('throws an exception if the specified judge has not scored the entry', function () {
|
||||
// Arrange
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
// Act
|
||||
$calculator('seating', Entry::factory()->create(), User::factory()->create());
|
||||
//Assert
|
||||
|
|
@ -45,7 +45,7 @@ it('correctly calculates final score for seating', function () {
|
|||
1005 => 90,
|
||||
];
|
||||
enterScore($judge, $entry, $scores);
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
$total = $calculator('seating', $entry, $judge);
|
||||
expect($total[0])->toBe(68.75);
|
||||
$expectedArray = [68.75, 80, 60, 70, 50];
|
||||
|
|
@ -64,7 +64,7 @@ it('correctly calculates final score for advancement', function () {
|
|||
1005 => 90,
|
||||
];
|
||||
enterScore($judge, $entry, $scores);
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$calculator = app(CalculateScoreSheetTotal::class);
|
||||
$total = $calculator('advancement', $entry, $judge);
|
||||
expect($total[0])->toBe(73.75);
|
||||
$expectedArray = [73.75, 90, 80, 60, 70];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
use App\Models\Audition;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('throws an exception when an invalid mode is requested', function () {
|
||||
$auditionService = new \App\Services\AuditionService();
|
||||
$this->expectException(\App\Exceptions\AuditionServiceException::class);
|
||||
$auditionService->getSubscores(new Audition(), 'invalid_mode');
|
||||
});
|
||||
it('throws an exception when an invalid sort is requested', function () {
|
||||
// Arrange
|
||||
$auditionService = new \App\Services\AuditionService();
|
||||
$this->expectException(\App\Exceptions\AuditionServiceException::class);
|
||||
// Act
|
||||
$auditionService->getSubscores(new Audition(), 'seating', 'invalid_sort');
|
||||
});
|
||||
it('throws an exception when an invalid audition is provided', function () {
|
||||
// Arrange
|
||||
$auditionService = new \App\Services\AuditionService();
|
||||
$this->expectException(\App\Exceptions\AuditionServiceException::class);
|
||||
$auditionService->getSubscores(new Audition(), 'seating', 'tiebreak');
|
||||
// Act & Assert
|
||||
|
||||
});
|
||||
it('gets subscores for an audition', function () {
|
||||
// Arrange
|
||||
loadSampleAudition();
|
||||
$auditionService = new \App\Services\AuditionService();
|
||||
// Act
|
||||
$subscores = $auditionService->getSubscores(Audition::find(1000), 'seating', 'tiebreak');
|
||||
// Assert
|
||||
expect($subscores->toArray())->toBe(Audition::find(1000)->scoringGuide->subscores->where('for_seating', true)->sortBy('tiebreak_order')->toArray());
|
||||
});
|
||||
Loading…
Reference in New Issue