diff --git a/app/Actions/Tabulation/EnterScore.php b/app/Actions/Tabulation/EnterScore.php index 407f4cb..ab7be4b 100644 --- a/app/Actions/Tabulation/EnterScore.php +++ b/app/Actions/Tabulation/EnterScore.php @@ -7,11 +7,9 @@ namespace App\Actions\Tabulation; use App\Exceptions\ScoreEntryException; -use App\Models\CalculatedScore; use App\Models\Entry; use App\Models\ScoreSheet; use App\Models\User; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; class EnterScore @@ -20,92 +18,18 @@ class EnterScore * @param User $user A user acting as the judge for this sheet * @param Entry $entry An entry to which this score should be assigned * @param array $scores Scores to be entered in the form of SubscoreID => score + * @param ScoreSheet|false $scoreSheet If this is an update to an existing scoresheet, pass it here + * @return ScoreSheet The scoresheet that was created or updated * * @throws ScoreEntryException */ public function __invoke(User $user, Entry $entry, array $scores, ScoreSheet|false $scoreSheet = false): ScoreSheet { - CalculatedScore::where('entry_id', $entry->id)->delete(); + // TODO: Remove the CalculatedScore model and table when rewrite is complete, they'll be obsolete + // CalculatedScore::where('entry_id', $entry->id)->delete(); $scores = collect($scores); - $this->basicChecks($user, $entry, $scores); - $this->checkJudgeAssignment($user, $entry); - $this->checkForExistingScore($user, $entry, $scoreSheet); - $this->validateScoresSubmitted($entry, $scores); - $entry->removeFlag('no_show'); - if ($scoreSheet instanceof ScoreSheet) { - $scoreSheet->update([ - 'user_id' => $user->id, - 'entry_id' => $entry->id, - 'subscores' => $this->subscoresForStorage($entry, $scores), - ]); - } else { - $scoreSheet = ScoreSheet::create([ - 'user_id' => $user->id, - 'entry_id' => $entry->id, - 'subscores' => $this->subscoresForStorage($entry, $scores), - ]); - } - return $scoreSheet; - } - - protected function subscoresForStorage(Entry $entry, Collection $scores) - { - $subscores = []; - foreach ($entry->audition->scoringGuide->subscores as $subscore) { - $subscores[$subscore->id] = [ - 'score' => $scores[$subscore->id], - 'subscore_id' => $subscore->id, - 'subscore_name' => $subscore->name, - ]; - } - - return $subscores; - } - - protected function checkForExistingScore(User $user, Entry $entry, $existingScoreSheet) - { - if (! $existingScoreSheet) { - if (ScoreSheet::where('user_id', $user->id)->where('entry_id', $entry->id)->exists()) { - throw new ScoreEntryException('That judge has already entered scores for that entry'); - } - } else { - if ($existingScoreSheet->user_id !== $user->id) { - throw new ScoreEntryException('Existing score sheet is from a different judge'); - } - if ($existingScoreSheet->entry_id !== $entry->id) { - throw new ScoreEntryException('Existing score sheet is for a different entry'); - } - } - } - - protected function validateScoresSubmitted(Entry $entry, Collection $scores) - { - $subscoresRequired = $entry->audition->scoringGuide->subscores; - - foreach ($subscoresRequired as $subscore) { - // check that there is an element in the $scores collection with the key = $subscore->id - if (! $scores->keys()->contains($subscore->id)) { - throw new ScoreEntryException('Invalid Score Submission'); - } - if ($scores[$subscore->id] > $subscore->max_score) { - throw new ScoreEntryException('Supplied subscore exceeds maximum allowed'); - } - } - } - - protected function checkJudgeAssignment(User $user, Entry $entry) - { - $check = DB::table('room_user') - ->where('room_id', $entry->audition->room_id) - ->where('user_id', $user->id)->exists(); - if (! $check) { - throw new ScoreEntryException('This judge is not assigned to judge this entry'); - } - } - - protected function basicChecks(User $user, Entry $entry, Collection $scores) - { + // Basic Validity Checks if (! $user->exists()) { throw new ScoreEntryException('User does not exist'); } @@ -118,9 +42,78 @@ class EnterScore if ($entry->audition->hasFlag('advancement_published')) { throw new ScoreEntryException('Cannot score an entry in an audition with published advancement'); } - $requiredScores = $entry->audition->scoringGuide->subscores()->count(); - if ($scores->count() !== $requiredScores) { + + // Check that the specified user is assigned to judge this entry + $check = DB::table('room_user') + ->where('room_id', $entry->audition->room_id) + ->where('user_id', $user->id)->exists(); + if (! $check) { + throw new ScoreEntryException('This judge is not assigned to judge this entry'); + } + + // Check if a score already exists + if (! $scoreSheet) { + if (ScoreSheet::where('user_id', $user->id)->where('entry_id', $entry->id)->exists()) { + throw new ScoreEntryException('That judge has already entered scores for that entry'); + } + } else { + if ($scoreSheet->user_id !== $user->id) { + throw new ScoreEntryException('Existing score sheet is from a different judge'); + } + if ($scoreSheet->entry_id !== $entry->id) { + throw new ScoreEntryException('Existing score sheet is for a different entry'); + } + } + + // Check the validity of submitted subscores, format array for storage, and sum score + $subscoresRequired = $entry->audition->scoringGuide->subscores; + $subscoresStorageArray = []; + $scoreSheetTotal = 0; + $maxPossible = 0; + if ($scores->count() !== $subscoresRequired->count()) { throw new ScoreEntryException('Invalid number of scores'); } + + foreach ($subscoresRequired as $subscore) { + // check that there is an element in the $scores collection with the key = $subscore->id + if (! $scores->keys()->contains($subscore->id)) { + throw new ScoreEntryException('Invalid Score Submission'); + } + if ($scores[$subscore->id] > $subscore->max_score) { + throw new ScoreEntryException('Supplied subscore exceeds maximum allowed'); + } + + // Add subscore to the storage array + $subscoresStorageArray[$subscore->id] = [ + 'score' => $scores[$subscore->id], + 'subscore_id' => $subscore->id, + 'subscore_name' => $subscore->name, + ]; + + // Multiply subscore by weight and add to the total + $scoreSheetTotal += ($subscore->weight * $scores[$subscore->id]); + + // Add weight to total weights + $maxPossible += ($subscore->weight * $subscore->max_score); + } + + $entry->removeFlag('no_show'); + if ($scoreSheet instanceof ScoreSheet) { + $scoreSheet->update([ + 'user_id' => $user->id, + 'entry_id' => $entry->id, + 'subscores' => $subscoresStorageArray, + 'sheet_total' => ($scoreSheetTotal / $maxPossible) * 100, + ]); + } else { + $scoreSheet = ScoreSheet::create([ + 'user_id' => $user->id, + 'entry_id' => $entry->id, + 'subscores' => $subscoresStorageArray, + 'sheet_total' => ($scoreSheetTotal / $maxPossible) * 100, + ]); + } + + return $scoreSheet; } }