auditionadmin/app/Actions/Tabulation/RankAuditionEntries.php

73 lines
2.1 KiB
PHP

<?php
/** @noinspection PhpUnhandledExceptionInspection */
namespace App\Actions\Tabulation;
use App\Exceptions\TabulationException;
use App\Models\Audition;
use Illuminate\Database\Eloquent\Collection;
class RankAuditionEntries
{
protected CalculateEntryScore $calculator;
public function __construct(CalculateEntryScore $calculator)
{
$this->calculator = $calculator;
}
public function booo()
{
return 'blah';
}
public function rank(string $mode, Audition $audition): Collection
{
$this->basicValidation($mode, $audition);
$entries = match ($mode) {
'seating' => $audition->entries()->forSeating()->with('scoreSheets')->get(),
'advancement' => $audition->entries()->forAdvancement()->with('scoreSheets')->get(),
};
foreach ($entries as $entry) {
$entry->setRelation('audition', $audition);
try {
$entry->score_totals = $this->calculator->calculate($mode, $entry);
} catch (TabulationException $ex) {
$entry->score_totals = [-1];
$entry->score_message = $ex->getMessage();
}
}
// Sort entries based on their total score, then by subscores in tiebreak order
$entries = $entries->sort(function ($a, $b) {
for ($i = 0; $i < count($a->score_totals); $i++) {
if ($a->score_totals[$i] > $b->score_totals[$i]) {
return -1;
} elseif ($a->score_totals[$i] < $b->score_totals[$i]) {
return 1;
}
}
return 0;
});
$rank = 1;
foreach ($entries as $entry) {
$entry->rank = $rank;
$rank++;
}
return $entries;
}
protected function basicValidation($mode, Audition $audition): void
{
if ($mode !== 'seating' && $mode !== 'advancement') {
throw new TabulationException('Mode must be seating or advancement');
}
if (! $audition->exists()) {
throw new TabulationException('Invalid audition provided');
}
}
}