id)); if ($audition->hasFlag('seats_published')) { $publishedSeats = Seat::where('audition_id', $audition->id) ->join('ensembles', 'seats.ensemble_id', '=', 'ensembles.id') ->orderBy('ensembles.rank') ->orderBy('seats.seat') ->select('seats.*') ->with(['ensemble', 'student.school']) ->get(); } else { $publishedSeats = false; } $ranker = app(RankAuditionEntries::class); // Get scored entries in order try { $scored_entries = $ranker($audition, 'seating'); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } $scored_entries->load(['student.doublers', 'student.school']); // Get unscored entries sorted by draw number $unscored_entries = $audition->entries() ->whereDoesntHave('totalScore') ->whereDoesntHave('flags', function ($query) { $query->where('flag_name', 'no_show'); }) ->whereDoesntHave('flags', function ($query) { $query->where('flag_name', 'failed_prelim'); }) ->with('student.school') ->withCount('scoreSheets') ->orderBy('draw_number') ->get(); // Get no show entries sorted by draw number $noshow_entries = $audition->entries() ->whereDoesntHave('totalScore') ->whereHas('flags', function ($query) { $query->where('flag_name', 'no_show'); }) ->with('student.school') ->orderBy('draw_number') ->get(); // Get failed prelim entries sorted by draw number $failed_prelim_entries = $audition->entries() ->whereDoesntHave('totalScore') ->whereHas('flags', function ($query) { $query->where('flag_name', 'failed_prelim'); }) ->with('student.school') ->orderBy('draw_number') ->get(); // Get Doublers $doublerData = Doubler::where('event_id', $audition->event_id) ->whereIn('student_id', $scored_entries->pluck('student_id')) ->get() ->keyBy('student_id'); $auditionHasUnresolvedDoublers = false; foreach ($doublerData as $doubler) { if (! is_null($doubler->accepted_entry)) { continue; } foreach ($doubler->entries() as $entry) { if ($entry->audition_id === $audition->id && $entry->hasFlag('declined')) { continue 2; } } $auditionHasUnresolvedDoublers = true; } $canSeat = ! $auditionHasUnresolvedDoublers && $unscored_entries->count() === 0; return view('tabulation.auditionSeating', compact('audition', 'scored_entries', 'unscored_entries', 'noshow_entries', 'failed_prelim_entries', 'doublerData', 'auditionHasUnresolvedDoublers', 'canSeat', 'seatingProposal', 'publishedSeats', ) ); } public function declineSeat(Audition $audition, Entry $entry) { $decider = app(DoublerDecision::class); try { $decider->decline($entry); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } return redirect()->route('seating.audition', ['audition' => $audition->id])->with('success', $entry->student->full_name().' has declined '.$audition->name); } public function massDecline(Audition $audition) { $decider = app(DoublerDecision::class); $validData = request()->validate([ 'decline-below' => ['required', 'integer', 'min:0'], ]); $ranker = app(RankAuditionEntries::class); // Get scored entries in order try { $scored_entries = $ranker($audition, 'seating'); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } $scored_entries->load(['student.doublers', 'student.school']); foreach ($scored_entries as $entry) { Debugbar::info('Starting entry '.$entry->student->full_name()); if ($entry->seatingRank < $validData['decline-below']) { Debugbar::info('Skipping '.$entry->student->full_name().' because they are ranked above decline threshold'); continue; } if ($entry->hasFlag('declined')) { Debugbar::info('Skipping '.$entry->student->full_name().' because they have already been declined'); continue; } if (! $entry->student->isDoublerInEvent($audition->event_id)) { Debugbar::info('Skipping '.$entry->student->full_name().' because they are not a doubler'); continue; } if ($entry->student->doublers->where('event_id', $audition->event_id)->first()->accepted_entry) { Debugbar::info('Skipping '.$entry->student->full_name().' because they have already accepted a seat'); continue; } try { $decider->decline($entry); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } } Cache::forget('rank_seating_'.$audition->id); return redirect()->route('seating.audition', ['audition' => $audition->id]); } public function acceptSeat(Audition $audition, Entry $entry) { $decider = app(DoublerDecision::class); try { $decider->accept($entry); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } return redirect()->route('seating.audition', ['audition' => $audition->id])->with('success', $entry->student->full_name().' has accepted '.$audition->name); } public function noshow( Audition $audition, Entry $entry ) { $recorder = app('App\Actions\Tabulation\EnterNoShow'); try { $msg = $recorder($entry); } catch (AuditionAdminException $e) { return redirect()->back()->with('error', $e->getMessage()); } return redirect()->route('seating.audition', [$audition])->with('success', $msg); } public function draftSeats( Audition $audition, Request $request ) { $ranker = app(RankAuditionEntries::class); $validated = $request->validate([ 'ensemble' => ['required', 'array'], 'ensemble.*' => ['required', 'integer', 'min:0'], ]); $proposedSeatingArray = []; try { $rankedEntries = $ranker($audition, 'seating'); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', ['audition' => $audition->id]) ->with('error', $e->getMessage()); } $rankedEntries = $rankedEntries->reject(function ($entry) { return $entry->hasFlag('declined'); }); $rankedEntries->load(['student.school']); $rankedEnsembles = Ensemble::orderBy('rank')->where('event_id', $audition->event_id)->get(); $ensembleRankOn = 1; foreach ($rankedEnsembles as $ensemble) { if (! Arr::has($validated['ensemble'], $ensemble->id)) { continue; } $proposedSeatingArray[$ensembleRankOn]['ensemble_id'] = $ensemble->id; $proposedSeatingArray[$ensembleRankOn]['ensemble_name'] = $ensemble->name; $proposedSeatingArray[$ensembleRankOn]['accept_count'] = $validated['ensemble'][$ensemble->id]; for ($n = 1; $n <= $validated['ensemble'][$ensemble->id]; $n++) { // Escape the loop if we're out of entries if ($rankedEntries->isEmpty()) { break; } $thisEntry = $rankedEntries->shift(); $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['seat'] = $n; $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_id'] = $thisEntry->id; $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_name'] = $thisEntry->student->full_name(); $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_school'] = $thisEntry->student->school->name; } $ensembleRankOn++; } $sessionKeyName = 'proposedSeatingArray-'.$audition->id; $request->session()->put($sessionKeyName, $proposedSeatingArray); return redirect()->route('seating.audition', ['audition' => $audition->id]); } public function clearDraft( Audition $audition ) { session()->forget('proposedSeatingArray-'.$audition->id); return redirect()->route('seating.audition', ['audition' => $audition->id]); } public function publishSeats( Audition $audition ) { $publisher = app('App\Actions\Tabulation\PublishSeats'); $seatingProposal = (session('proposedSeatingArray-'.$audition->id)); $proposal = []; foreach ($seatingProposal as $ensemble) { $ensembleId = $ensemble['ensemble_id']; if (isset($ensemble['seats'])) { foreach ($ensemble['seats'] as $seat) { $proposal[] = [ 'ensemble_id' => $ensembleId, 'audition_id' => $audition->id, 'seat' => $seat['seat'], 'entry_id' => $seat['entry_id'], ]; } } } try { $publisher($audition, $proposal); } catch (AuditionAdminException $e) { return redirect()->route('seating.audition', [$audition])->with('error', $e->getMessage()); } session()->forget('proposedSeatingArray-'.$audition->id); return redirect()->route('seating.audition', [$audition]); } public function unpublishSeats( Audition $audition ) { $unpublisher = app('App\Actions\Tabulation\UnpublishSeats'); $unpublisher($audition); session()->forget('proposedSeatingArray-'.$audition->id); return redirect()->route('seating.audition', [$audition]); } }