259 lines
10 KiB
PHP
259 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Tabulation;
|
|
|
|
use App\Actions\Tabulation\GetAuditionSeats;
|
|
use App\Actions\Tabulation\RankAuditionEntries;
|
|
use App\Exceptions\AuditionAdminException;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Audition;
|
|
use App\Models\Doubler;
|
|
use App\Models\Ensemble;
|
|
use App\Models\Entry;
|
|
use App\Models\Seat;
|
|
use Debugbar;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
use function redirect;
|
|
|
|
class SeatAuditionFormController extends Controller
|
|
{
|
|
public function showForm(Request $request, Audition $audition)
|
|
{
|
|
$seatingProposal = (session('proposedSeatingArray-'.$audition->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', 'entry.student.school'])
|
|
->get();
|
|
} else {
|
|
$publishedSeats = false;
|
|
}
|
|
|
|
$ranker = app(RankAuditionEntries::class);
|
|
// Get scored entries in order
|
|
$scored_entries = $ranker($audition, 'seating');
|
|
$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')
|
|
->orderBy('draw_number', 'asc')
|
|
->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', 'asc')
|
|
->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', 'asc')
|
|
->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;
|
|
Debugbar::info($seatingProposal);
|
|
|
|
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)
|
|
{
|
|
$entry->addFlag('declined');
|
|
Cache::forget('rank_seating_'.$entry->audition_id);
|
|
|
|
return redirect()->route('seating.audition', ['audition' => $audition->id])->with('success',
|
|
$entry->student->full_name().' has declined '.$audition->name);
|
|
}
|
|
|
|
public function acceptSeat(Audition $audition, Entry $entry)
|
|
{
|
|
$doublerData = Doubler::findDoubler($entry->student_id, $audition->event_id);
|
|
foreach ($doublerData->entries() as $doublerEntry) {
|
|
if (! $doublerEntry->totalScore && ! $doublerEntry->hasFlag('declined') && ! $doublerEntry->hasFlag('no_show') && ! $doublerEntry->hasFlag('failed_prelim')) {
|
|
return redirect()->route('seating.audition', ['audition' => $audition->id])->with('error',
|
|
'Cannot accept seating for '.$entry->student->full_name().' because student has unscored entries');
|
|
}
|
|
}
|
|
foreach ($doublerData->entries() as $doublerEntry) {
|
|
Cache::forget('rank_seating_'.$doublerEntry->audition_id);
|
|
if ($doublerEntry->id !== $entry->id && ! $doublerEntry->hasFlag('no_show') && ! $doublerEntry->hasFlag('failed_prelim') && ! $doublerEntry->hasFlag('declined')) {
|
|
$doublerEntry->addFlag('declined');
|
|
}
|
|
}
|
|
|
|
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 = [];
|
|
$rankedEntries = $ranker($audition, 'seating');
|
|
$rankedEntries = $rankedEntries->reject(function ($entry) {
|
|
return $entry->hasFlag('declined');
|
|
});
|
|
|
|
$rankedEntries->load(['student.school']);
|
|
$rankedEnembles = Ensemble::orderBy('rank')->where('event_id', $audition->event_id)->get();
|
|
$ensembleRankOn = 1;
|
|
foreach ($rankedEnembles 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, 10);
|
|
|
|
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'],
|
|
];
|
|
}
|
|
}
|
|
}
|
|
$publisher($audition, $proposal);
|
|
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]);
|
|
}
|
|
|
|
protected function pickRightPanel(Audition $audition, array $seatable)
|
|
{
|
|
if ($audition->hasFlag('seats_published')) {
|
|
$resultsWindow = new GetAuditionSeats;
|
|
$rightPanel['view'] = 'tabulation.auditionSeating-show-published-seats';
|
|
$rightPanel['data'] = $resultsWindow($audition);
|
|
|
|
return $rightPanel;
|
|
}
|
|
if ($seatable['allScored'] == false || $seatable['doublersResolved'] == false) {
|
|
$rightPanel['view'] = 'tabulation.auditionSeating-unable-to-seat-card';
|
|
$rightPanel['data'] = $seatable;
|
|
|
|
return $rightPanel;
|
|
}
|
|
|
|
$rightPanel['view'] = 'tabulation.auditionSeating-right-complete-not-published';
|
|
$rightPanel['data'] = $this->auditionService->getSeatingLimits($audition);
|
|
|
|
return $rightPanel;
|
|
}
|
|
}
|