CalculateScoreSheetTotal working
This commit is contained in:
parent
0eda3ab32e
commit
49ebfda9a8
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace App\Actions;
|
||||
|
||||
use App\Exceptions\TabulationException;
|
||||
use App\Models\Entry;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\User;
|
||||
|
||||
class CalculateScoreSheetTotal
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(string $mode, Entry $entry, User $judge): array
|
||||
{
|
||||
$this->basicValidations($mode, $entry, $judge);
|
||||
$scoreSheet = ScoreSheet::where('entry_id', $entry->id)->where('user_id', $judge->id)->first();
|
||||
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'),
|
||||
};
|
||||
$scoreTotal = 0;
|
||||
$weightsTotal = 0;
|
||||
$scoreArray = [];
|
||||
foreach ($subscores as $subscore) {
|
||||
$weight = $subscore['weight'];
|
||||
$score = $scoreSheet->subscores[$subscore->id]['score'];
|
||||
$scoreArray[] = $score;
|
||||
$scoreTotal += ($score * $weight);
|
||||
$weightsTotal += $weight;
|
||||
}
|
||||
$finalScore = $scoreTotal / $weightsTotal;
|
||||
// put $final score at the beginning of the $ScoreArray
|
||||
array_unshift($scoreArray, $finalScore);
|
||||
return $scoreArray;
|
||||
}
|
||||
|
||||
protected function basicValidations($mode, $entry, $judge): void
|
||||
{
|
||||
if ($mode !== 'seating' and $mode !== 'advancement') {
|
||||
throw new TabulationException('Invalid mode requested. Mode must be seating or advancement');
|
||||
}
|
||||
if (! $entry->exists()) {
|
||||
throw new TabulationException('Invalid entry provided');
|
||||
}
|
||||
if (! $judge->exists()) {
|
||||
throw new TabulationException('Invalid judge provided');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,21 +2,12 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Events\AuditionChange;
|
||||
use App\Events\EntryChange;
|
||||
use App\Events\ScoreSheetChange;
|
||||
use App\Events\ScoringGuideChange;
|
||||
use App\Events\SeatingLimitChange;
|
||||
use App\Listeners\RefreshAuditionCache;
|
||||
use App\Listeners\RefreshEntryCache;
|
||||
use App\Listeners\RefreshScoreSheetCache;
|
||||
use App\Listeners\RefreshScoringGuideCache;
|
||||
use App\Listeners\RefreshSeatingLimitCache;
|
||||
use App\Models\Audition;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Room;
|
||||
use App\Models\RoomUser;
|
||||
use App\Models\School;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\ScoringGuide;
|
||||
use App\Models\SeatingLimit;
|
||||
use App\Models\Student;
|
||||
|
|
@ -40,10 +31,7 @@ use App\Services\EntryService;
|
|||
use App\Services\ScoreService;
|
||||
use App\Services\SeatingService;
|
||||
use App\Services\TabulationService;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Models\ScoreSheet;
|
||||
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -52,36 +40,36 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->singleton(DrawService::class, function () {
|
||||
return new DrawService();
|
||||
// $this->app->singleton(DrawService::class, function () {
|
||||
// return new DrawService();
|
||||
// });
|
||||
//
|
||||
// $this->app->singleton(AuditionService::class, function () {
|
||||
// return new AuditionService();
|
||||
// });
|
||||
//
|
||||
// $this->app->singleton(SeatingService::class, function ($app) {
|
||||
// return new SeatingService($app->make(TabulationService::class));
|
||||
// });
|
||||
//
|
||||
$this->app->singleton(EntryService::class, function () {
|
||||
return new EntryService();
|
||||
});
|
||||
|
||||
$this->app->singleton(AuditionService::class, function () {
|
||||
return new AuditionService();
|
||||
});
|
||||
|
||||
$this->app->singleton(SeatingService::class, function ($app) {
|
||||
return new SeatingService($app->make(TabulationService::class));
|
||||
});
|
||||
|
||||
$this->app->singleton(EntryService::class, function ($app) {
|
||||
return new EntryService($app->make(AuditionService::class));
|
||||
});
|
||||
|
||||
$this->app->singleton(ScoreService::class, function ($app) {
|
||||
return new ScoreService($app->make(AuditionService::class), $app->make(EntryService::class));
|
||||
});
|
||||
|
||||
$this->app->singleton(TabulationService::class, function ($app) {
|
||||
return new TabulationService(
|
||||
$app->make(AuditionService::class),
|
||||
$app->make(ScoreService::class),
|
||||
$app->make(EntryService::class));
|
||||
});
|
||||
|
||||
$this->app->singleton(DoublerService::class, function ($app) {
|
||||
return new DoublerService($app->make(AuditionService::class), $app->make(TabulationService::class), $app->make(SeatingService::class));
|
||||
$this->app->singleton(ScoreService::class, function () {
|
||||
return new ScoreService();
|
||||
});
|
||||
//
|
||||
// $this->app->singleton(TabulationService::class, function ($app) {
|
||||
// return new TabulationService(
|
||||
// $app->make(AuditionService::class),
|
||||
// $app->make(ScoreService::class),
|
||||
// $app->make(EntryService::class));
|
||||
// });
|
||||
//
|
||||
// $this->app->singleton(DoublerService::class, function ($app) {
|
||||
// return new DoublerService($app->make(AuditionService::class), $app->make(TabulationService::class), $app->make(SeatingService::class));
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -102,6 +90,5 @@ class AppServiceProvider extends ServiceProvider
|
|||
User::observe(UserObserver::class);
|
||||
SeatingLimit::observe(SeatingLimitObserver::class);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Services;
|
||||
|
||||
use App\Models\Entry;
|
||||
use App\Models\User;
|
||||
|
||||
class ScoreService
|
||||
{
|
||||
|
|
@ -21,5 +22,10 @@ class ScoreService
|
|||
return $requiredJudges === $scoreSheets;
|
||||
}
|
||||
|
||||
public function scoreSheetTotal(string $mode, User $judge, Entry $entry): float
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
use App\Actions\CalculateScoreSheetTotal;
|
||||
use App\Exceptions\TabulationException;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Room;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
beforeEach(function () {
|
||||
$this->calculator = new CalculateScoreSheetTotal();
|
||||
});
|
||||
it('throws an exception if an invalid mode is called for', function () {
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$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('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('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();
|
||||
// Act
|
||||
$calculator('seating', Entry::factory()->create(), User::factory()->create());
|
||||
//Assert
|
||||
})->throws(TabulationException::class, 'No score sheet by that judge for that entry');
|
||||
it('correctly calculates final score for seating', function () {
|
||||
loadSampleAudition();
|
||||
$judge = User::factory()->create();
|
||||
Room::find(1000)->addJudge($judge);
|
||||
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||
$scores = [
|
||||
1001 => 50,
|
||||
1002 => 60,
|
||||
1003 => 70,
|
||||
1004 => 80,
|
||||
1005 => 90,
|
||||
];
|
||||
enterScore($judge, $entry, $scores);
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$total = $calculator('seating', $entry, $judge);
|
||||
expect($total[0])->toBe(68.75);
|
||||
$expectedArray = [68.75, 80, 60, 70, 50];
|
||||
expect($total)->toBe($expectedArray);
|
||||
});
|
||||
it('correctly calculates final score for advancement', function () {
|
||||
loadSampleAudition();
|
||||
$judge = User::factory()->create();
|
||||
Room::find(1000)->addJudge($judge);
|
||||
$entry = Entry::factory()->create(['audition_id' => 1000]);
|
||||
$scores = [
|
||||
1001 => 50,
|
||||
1002 => 60,
|
||||
1003 => 70,
|
||||
1004 => 80,
|
||||
1005 => 90,
|
||||
];
|
||||
enterScore($judge, $entry, $scores);
|
||||
$calculator = new CalculateScoreSheetTotal();
|
||||
$total = $calculator('advancement', $entry, $judge);
|
||||
expect($total[0])->toBe(73.75);
|
||||
$expectedArray = [73.75, 90, 80, 60, 70];
|
||||
expect($total)->toBe($expectedArray);
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Audition;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
use function Pest\Laravel\get;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->audition = Audition::factory()->create();
|
||||
$this->r = route('seating.audition', $this->audition);
|
||||
});
|
||||
|
||||
it('denies access to a guest', function () {
|
||||
get($this->r)
|
||||
->assertRedirect(route('home'));
|
||||
});
|
||||
|
||||
it('denies access to a normal user', function () {
|
||||
actAsNormal();
|
||||
get($this->r)
|
||||
->assertRedirect(route('dashboard'))
|
||||
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||
});
|
||||
it('grants access to admin', function () {
|
||||
// Arrange
|
||||
actAsAdmin();
|
||||
// Act & Assert
|
||||
get($this->r)->assertOk();
|
||||
});
|
||||
it('grants access to tabulators', function () {
|
||||
// Arrange
|
||||
actAsTab();
|
||||
// Act & Assert
|
||||
get($this->r)->assertOk();
|
||||
});
|
||||
|
|
@ -14,13 +14,6 @@ uses(RefreshDatabase::class);
|
|||
beforeEach(function () {
|
||||
$this->scoreService = new ScoreService();
|
||||
});
|
||||
it('can record a score', function () {
|
||||
// Arrange
|
||||
// run the seeder AuditionWithScoringGuideAndRoom
|
||||
artisan('db:seed', ['--class' => 'AuditionWithScoringGuideAndRoom']);
|
||||
// Act & Assert
|
||||
expect(Audition::find(1000)->name)->toBe('Test Audition');
|
||||
});
|
||||
|
||||
it('can check if an entry is fully scored', function () {
|
||||
$room = Room::factory()->create();
|
||||
|
|
|
|||
Loading…
Reference in New Issue