auditionadmin/app/Actions/Tabulation/RankAuditionEntries.php

118 lines
5.4 KiB
PHP

<?php
/** @noinspection PhpUnhandledExceptionInspection */
namespace App\Actions\Tabulation;
use App\Exceptions\AuditionAdminException;
use App\Models\Audition;
use App\Models\Entry;
use Illuminate\Support\Collection;
class RankAuditionEntries
{
/**
* Get ranked entries for the provided audition for either seating or advancement.
*
* If the rank_type is seating, the ranked entries are returned in descending order of seating total.
* If the rank_type is advancement, the ranked entries are returned in descending order of advancement total.
*
* The ranked entries are returned as a Collection of Entry objects.
*
* @param string $rank_type advancement|seating
* @return Collection<Entry>|void
*
* @throws AuditionAdminException
*/
public function __invoke(Audition $audition, string $rank_type): Collection|Entry
{
if ($rank_type !== 'seating' && $rank_type !== 'advancement') {
throw new AuditionAdminException('Invalid rank type (must be seating or advancement)');
}
$cache_duration = 15;
if ($rank_type === 'seating') {
return cache()->remember('rank_seating_'.$audition->id, $cache_duration, function () use ($audition) {
return $this->get_seating_ranks($audition);
});
}
return cache()->remember('rank_advancement_'.$audition->id, $cache_duration, function () use ($audition) {
return $this->get_advancement_ranks($audition);
});
}
private function get_seating_ranks(Audition $audition): Collection|Entry
{
if ($audition->bonusScore()->count() > 0) {
$totalColumn = 'seating_total_with_bonus';
} else {
$totalColumn = 'seating_total';
}
$sortedEntries = $audition->entries()
->whereHas('totalScore')
->with('totalScore')
->with('student.school')
->with('audition')
->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id')
->orderBy('entry_total_scores.'.$totalColumn, 'desc')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[0]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[1]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[2]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[3]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[4]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[5]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[6]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[7]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[8]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[9]"), -999999) DESC')
->select('entries.*')
->get();
$rankOn = 1;
foreach ($sortedEntries as $entry) {
if ($entry->hasFlag('declined')) {
$entry->seatingRank = 'declined';
} else {
$entry->seatingRank = $rankOn;
$rankOn++;
}
}
return $sortedEntries;
}
private function get_advancement_ranks(Audition $audition): Collection|Entry
{
$sortedEntries = $audition->entries()
->whereHas('totalScore')
->with('totalScore')
->with('student.school')
->with('audition')
->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id')
->orderBy('entry_total_scores.advancement_total', 'desc')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[0]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[1]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[2]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[3]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[4]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[5]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[6]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[7]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[8]"), -999999) DESC')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.advancement_subscore_totals, "$[9]"), -999999) DESC')
->select('entries.*')
->get();
$n = 1;
foreach ($sortedEntries as $entry) {
$entry->advancementRank = $n;
$n++;
}
return $sortedEntries;
}
}