auditionadmin/app/Http/Controllers/NominationEnsembles/ScobdaNominationSeatingCont...

124 lines
4.5 KiB
PHP

<?php
namespace App\Http\Controllers\NominationEnsembles;
use App\Http\Controllers\Controller;
use App\Models\NominationEnsemble;
use App\Models\NominationEnsembleEntry;
use App\Models\Student;
use function redirect;
class ScobdaNominationSeatingController extends Controller implements NominationSeatingController
{
public function index()
{
$shirtReportType = request()->get('shirtReportType') || null;
$ensembles = NominationEnsemble::all();
$ensemble = null;
$shirtCounts = ($shirtReportType == 'full') ? $this->totalShirtCount() : null;
return view('nomination_ensembles.scobda.admin.seating.index',
compact('ensembles', 'ensemble', 'shirtReportType', 'shirtCounts'));
}
protected function totalShirtCount()
{
$acceptedNominationEntries = NominationEnsembleEntry::where('data->accepted', true)->with('student')->get();
$possibleSizes = Student::$shirtSizes;
$shirtCounts = ['none' => 0];
foreach ($possibleSizes as $shortSize => $size) {
$shirtCounts[$shortSize] = 0;
}
foreach ($acceptedNominationEntries as $entry) {
$shirtSize = $entry->student->optional_data['shirt_size'] ?? 'none';
$shirtCounts[$shirtSize] += 1;
}
return $shirtCounts;
}
public function show(NominationEnsemble $ensemble)
{
$ensembles = NominationEnsemble::all();
$acceptedNominations = NominationEnsembleEntry::where('nomination_ensemble_id', $ensemble->id)
->where('data->accepted', true)
->orderByRaw('CAST(data->"$.rank" AS UNSIGNED)')
->get();
$acceptedNominations = $acceptedNominations->groupBy(function ($item) {
return $item->data['instrument'];
});
return view('nomination_ensembles.scobda.admin.seating.index',
compact('ensembles', 'ensemble', 'acceptedNominations'));
}
public function seat(NominationEnsemble $ensemble)
{
$nominations = NominationEnsembleEntry::where('nomination_ensemble_id',
$ensemble->id)->orderByRaw('CAST(data->"$.rank" AS UNSIGNED)')->inRandomOrder()->get();
$rankGroupedNominations = $nominations->groupBy(function ($entry) {
return $entry->data['rank'];
});
$validData = request()->validate([
'action' => ['required', 'in:seat,clear'],
]);
$action = $validData['action'];
if ($action == 'clear') {
foreach ($nominations as $nomination) {
$data = $nomination->data;
unset($data['accepted']);
$nomination->update(['data' => $data]);
}
$data = $ensemble->data;
$data['seated'] = false;
$ensemble->data = $data;
$ensemble->update();
return redirect()->route('nomination.admin.seating.show',
['ensemble' => $ensemble])->with('Seating Cleared');
}
$acceptedNominations = collect();
$rankOn = 1;
// Collect students to add to the ensemble
while ($rankOn <= $ensemble->data['max_nominations'] && $rankGroupedNominations->has($rankOn)) {
// If were at or over the target size of the ensemble, stop adding people
if ($acceptedNominations->count() >= $ensemble->data['target_size']) {
break;
}
// Add people of the current rank to the ensemble
foreach ($rankGroupedNominations[$rankOn] as $nomination) {
$acceptedNominations->push($nomination);
}
$rankOn++;
// If we want to round down the ensemble size, quit adding people if hte next rank will exceed the target
if (
$rankGroupedNominations->has($rankOn) &&
$acceptedNominations->count() + $rankGroupedNominations[$rankOn]->count() >= $ensemble->data['target_size'] &&
$ensemble->data['rounding_direction'] === 'down'
) {
break;
}
}
foreach ($acceptedNominations as $nomination) {
$data = $nomination->data;
$data['accepted'] = true;
$nomination->update(['data' => $data]);
}
$data = $ensemble->data;
$data['seated'] = true;
$ensemble->data = $data;
$ensemble->update();
return redirect()->route('nomination.admin.seating.show', ['ensemble' => $ensemble])->with('Seating Complete');
}
}