Progress on seating form

This commit is contained in:
Matt Young 2025-06-17 00:43:50 -05:00
parent 349da644b7
commit ad24a67baa
6 changed files with 106 additions and 11 deletions

View File

@ -6,6 +6,7 @@ namespace App\Actions\Tabulation;
use App\Exceptions\AuditionAdminException; use App\Exceptions\AuditionAdminException;
use App\Models\Audition; use App\Models\Audition;
use App\Models\Entry;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
class RankAuditionEntries class RankAuditionEntries
@ -19,7 +20,7 @@ class RankAuditionEntries
* The ranked entries are returned as a Collection of Entry objects. * The ranked entries are returned as a Collection of Entry objects.
* *
* @param string $rank_type advancement|seating * @param string $rank_type advancement|seating
* @return Collection|void * @return Collection<Entry>|void
* *
* @throws AuditionAdminException * @throws AuditionAdminException
*/ */
@ -45,6 +46,7 @@ class RankAuditionEntries
->whereHas('totalScore') ->whereHas('totalScore')
->with('totalScore') ->with('totalScore')
->with('student.school') ->with('student.school')
->with('audition')
->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id') ->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id')
->orderBy('entry_total_scores.seating_total', 'desc') ->orderBy('entry_total_scores.seating_total', 'desc')
->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[0]"), -999999) DESC') ->orderByRaw('COALESCE(JSON_EXTRACT(entry_total_scores.seating_subscore_totals, "$[0]"), -999999) DESC')
@ -67,6 +69,7 @@ class RankAuditionEntries
->whereHas('totalScore') ->whereHas('totalScore')
->with('totalScore') ->with('totalScore')
->with('student.school') ->with('student.school')
->with('audition')
->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id') ->join('entry_total_scores', 'entries.id', '=', 'entry_total_scores.entry_id')
->orderBy('entry_total_scores.advancement_total', 'desc') ->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, "$[0]"), -999999) DESC')

View File

@ -49,12 +49,21 @@ class SeatAuditionFormController extends Controller
->orderBy('draw_number', 'asc') ->orderBy('draw_number', 'asc')
->get(); ->get();
// Get Doubler Data
$doubler_data = [];
foreach ($scored_entries as $e) {
if ($e->student->isDoublerInEvent($audition->event_id)) {
$doubler_data[$e->id] = $e->student->entriesForEvent($e->audition->event_id);
}
}
return view('tabulation.auditionSeating', return view('tabulation.auditionSeating',
compact('audition', compact('audition',
'scored_entries', 'scored_entries',
'unscored_entries', 'unscored_entries',
'noshow_entries', 'noshow_entries',
'failed_prelim_entries') 'failed_prelim_entries',
'doubler_data', )
); );
} }

View File

@ -60,6 +60,15 @@ class Audition extends Model
return $this->belongsToMany(BonusScoreDefinition::class, 'bonus_score_audition_assignment'); return $this->belongsToMany(BonusScoreDefinition::class, 'bonus_score_audition_assignment');
} }
public function SeatingLimits(): HasMany
{
return $this->hasMany(SeatingLimit::class)
->with('ensemble')
->join('ensembles', 'seating_limits.ensemble_id', '=', 'ensembles.id')
->orderBy('ensembles.rank')
->select('seating_limits.*');
}
public function display_fee(): string public function display_fee(): string
{ {
return '$'.number_format($this->entry_fee / 100, 2); return '$'.number_format($this->entry_fee / 100, 2);

View File

@ -2,7 +2,9 @@
namespace App\Models; namespace App\Models;
use App\Actions\Tabulation\RankAuditionEntries;
use App\Enums\EntryFlags; use App\Enums\EntryFlags;
use App\Exceptions\AuditionAdminException;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@ -24,6 +26,33 @@ class Entry extends Model
return $this->hasOne(EntryTotalScore::class); return $this->hasOne(EntryTotalScore::class);
} }
/**
* @throws AuditionAdminException
*/
public function rank(string $type)
{
$ranker = app(RankAuditionEntries::class);
if ($type !== 'seating' && $type !== 'advancement') {
throw new AuditionAdminException('Invalid type specified. Must be either seating or advancement.');
}
// Return false if no score. If we have no score, we can't have a rank
if (! $this->totalScore) {
return false;
}
// Get the ranked entries for this entries audition
$rankedEntries = $ranker($this->audition, $type);
// Find position of current entry in the ranked entries (1-based index)
$position = $rankedEntries->search(fn ($entry) => $entry->id === $this->id);
// Return false if entry not found, otherwise return 1-based position
return $position === false ? false : $position + 1;
}
public function student(): BelongsTo public function student(): BelongsTo
{ {
return $this->belongsTo(Student::class); return $this->belongsTo(Student::class);

View File

@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Support\Collection;
class Student extends Model class Student extends Model
{ {
@ -103,4 +104,19 @@ class Student extends Model
'student_id' => $this->id, 'student_id' => $this->id,
])->exists(); ])->exists();
} }
public function entriesForEvent(Event|int $event): Collection
{
$eventId = $event instanceof Event ? $event->id : $event;
return Entry::query()
->where('student_id', $this->id)
->whereHas('audition', function ($query) use ($event) {
$query->where('event_id', $event);
})
->with('audition.SeatingLimits') // Eager load the audition relation if needed
->with('totalScore')
->get();
}
} }

View File

@ -25,18 +25,47 @@
</x-table.th> </x-table.th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody class="divide-y divide-gray-200">
@foreach($scored_entries as $entry) @foreach($scored_entries as $entry)
<tr> <tr>
<x-table.td>{{ $loop->iteration }}</x-table.td> <x-table.td class="align-top">{{ $loop->iteration }}</x-table.td>
<x-table.td>{{ $entry->id }}</x-table.td> <x-table.td class="align-top">{{ $entry->id }}</x-table.td>
<x-table.td>{{ $entry->draw_number }}</x-table.td> <x-table.td class="align-top">{{ $entry->draw_number }}</x-table.td>
<x-table.td class="flex flex-col"> <x-table.td class="align-top">
<span>{{ $entry->student->full_name() }}</span> <div>{{ $entry->student->full_name() }}</div>
<span class="text-xs text-gray-400">{{ $entry->student->school->name }}</span> <div class="text-xs text-gray-400">{{ $entry->student->school->name }}</div>
</x-table.td> </x-table.td>
<x-table.td>Doubler to Come</x-table.td> <x-table.td class="align-top">
<x-table.td>{{ $entry->totalScore->seating_total }}</x-table.td> @if( isset($doubler_data[$entry->id]) )
{{-- Check if this entry is a doubler --}}
@foreach($doubler_data[$entry->id] as $de)
{{-- If it is, render doubler blocks --}}
<div class="border-2 border-gray-200 p-2 m-2">
{{-- @var \App\Models\Entry $de --}}
<div class="font-semibold mb-2">
{{ $de->audition->name }} #{{$de->draw_number}} ({{ $de->id }})
</div>
@php($unscored = $de->audition->unscoredEntries()->count())
@if($unscored > 0)
<div>{{ $unscored }} Unscored Entries</div>
@endif
@if(! $de->rank('seating'))
<div class="text-red-500">THIS ENTRY NOT SCORED</div>
@else
<div>Ranked: {{ $de->rank('seating') }}</div>
<div class="mt-2">
Acceptance Limits<br>
@foreach ($de->audition->SeatingLimits as $limit)
{{ $limit->ensemble->name }} -> {{ $limit->maximum_accepted }}
<br>
@endforeach
</div>
@endif
</div>
@endforeach
@endif
</x-table.td>
<x-table.td class="align-top">{{ $entry->totalScore->seating_total }}</x-table.td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>