auditionadmin/app/Http/Controllers/Tabulation/SeatAuditionFormController.php

182 lines
6.6 KiB
PHP

<?php
namespace App\Http\Controllers\Tabulation;
use App\Actions\Entries\DoublerDecision;
use App\Actions\Tabulation\CalculateEntryScore;
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\Services\AuditionService;
use App\Services\DoublerService;
use App\Services\EntryService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use function redirect;
class SeatAuditionFormController extends Controller
{
protected CalculateEntryScore $calc;
protected DoublerService $doublerService;
protected RankAuditionEntries $ranker;
protected EntryService $entryService;
protected AuditionService $auditionService;
protected DoublerDecision $decider;
public function __construct(
CalculateEntryScore $calc,
RankAuditionEntries $ranker,
DoublerService $doublerService,
EntryService $entryService,
AuditionService $auditionService,
DoublerDecision $decider,
) {
$this->calc = $calc;
$this->ranker = $ranker;
$this->doublerService = $doublerService;
$this->entryService = $entryService;
$this->auditionService = $auditionService;
$this->decider = $decider;
}
public function __invoke(Request $request, Audition $audition)
{
// If a seating proposal was posted, deal wth it
if ($request->method() == 'POST' && $request->input('ensembleAccept')) {
$requestedEnsembleAccepts = $request->input('ensembleAccept');
} else {
$requestedEnsembleAccepts = false;
}
// Deal with a mass no-show request
if ($request->input('mass-no-show')) {
$entries = $audition->entries()->forSeating()->withCount('scoreSheets')->with('flags')->get();
foreach ($entries as $entry) {
if ($entry->scoreSheets_count == 0 && ! $entry->hasFlag('no_show')) {
$entry->addFlag('no_show');
}
Cache::forget('entryScore-'.$entry->id.'-seating');
Cache::forget('entryScore-'.$entry->id.'-advancement');
}
Cache::forget('audition'.$audition->id.'seating');
Cache::forget('audition'.$audition->id.'advancement');
}
$entryData = [];
$entries = $this->ranker->rank('seating', $audition);
// Deal with mass decline doubler request
if ($request->input('decline-below')) {
Cache::forget('audition'.$audition->id.'seating');
$changes_made = false;
foreach ($entries as $entry) {
$doublerData = $this->doublerService->entryDoublerData($entry);
if ($doublerData && ! $entry->hasFlag('declined') && $entry->rank > $request->input('decline-below')) {
try {
$this->decider->decline($entry);
$changes_made = true;
} catch (AuditionAdminException $e) {
return redirect()->back()->with('error', $e->getMessage());
}
}
}
if ($changes_made) {
return redirect()->back();
}
}
$entries->load('student.school');
$entries->load('student.doublerRequests');
$seatable = [
'allScored' => true,
'doublersResolved' => true,
];
foreach ($entries as $entry) {
$totalScoreColumn = 'No Score';
$fullyScored = false;
if ($entry->score_totals) {
$totalScoreColumn = $entry->score_totals[0] >= 0 ? $entry->score_totals[0] : $entry->score_message;
$fullyScored = $entry->score_totals[0] >= 0;
}
// No Shows are fully scored
if ($entry->hasFlag('no_show')) {
$fullyScored = true;
}
$doublerData = $this->doublerService->entryDoublerData($entry);
$entryData[] = [
'rank' => $entry->rank,
'id' => $entry->id,
'studentName' => $entry->student->full_name(),
'schoolName' => $entry->student->school->name,
'drawNumber' => $entry->draw_number,
'totalScore' => $totalScoreColumn,
'fullyScored' => $fullyScored,
'hasBonusScores' => $entry->bonus_scores_count > 0,
'doubleData' => $doublerData,
'doublerRequest' => $entry->student->doublerRequests()->where('event_id',
$audition->event_id)->first()?->request,
];
// If this entries double decision isn't made, block seating
if ($doublerData && $doublerData[$entry->id]['status'] == 'undecided') {
$seatable['doublersResolved'] = false;
}
// If entry is unscored, block seating
if (! $fullyScored) {
$seatable['allScored'] = false;
}
}
$rightPanel = $this->pickRightPanel($audition, $seatable);
$seatableEntries = [];
if ($seatable['doublersResolved'] && $seatable['allScored']) {
$seatableEntries = $entries->reject(function ($entry) {
if ($entry->hasFlag('declined')) {
return true;
}
if ($entry->hasFlag('no_show')) {
return true;
}
if ($entry->hasFlag('failed_prelim')) {
return true;
}
return false;
});
}
return view('tabulation.auditionSeating',
compact('entryData', 'audition', 'rightPanel', 'seatableEntries', 'requestedEnsembleAccepts'));
}
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;
}
}