Rewrite tabulation #14

Merged
okorpheus merged 43 commits from rewrite-tabulation into master 2024-07-14 05:36:29 +00:00
10 changed files with 92 additions and 24 deletions
Showing only changes of commit 93c970c26e - Show all commits

View File

@ -4,13 +4,14 @@ namespace App\Http\Controllers\Tabulation;
use App\Http\Controllers\Controller;
use App\Models\Entry;
use App\Models\EntryFlag;
use App\Services\DoublerService;
use App\Services\EntryService;
use Illuminate\Support\Facades\Cache;
class DoublerDecisionController extends Controller
{
protected $doublerService;
protected $entryService;
public function __construct(DoublerService $doublerService, EntryService $entryService)
@ -29,8 +30,8 @@ class DoublerDecisionController extends Controller
}
}
$returnMessage = $entry->student->full_name().' accepted seating in '.$entry->audition->name;
$this->clearCache($entry);
return redirect()->back()->with('success', $returnMessage);
@ -45,7 +46,16 @@ class DoublerDecisionController extends Controller
$entry->addFlag('declined');
$returnMessage = $entry->student->full_name().' declined seating in '.$entry->audition->name;
$this->clearCache($entry);
return redirect()->back()->with('success', $returnMessage);
}
protected function clearCache($entry)
{
$cacheKey = 'event'.$entry->audition->event_id.'doublers-seating';
Cache::forget($cacheKey);
$cacheKey = 'event'.$entry->audition->event_id.'doublers-advancement';
Cache::forget($cacheKey);
}
}

View File

@ -42,7 +42,10 @@ class SeatAuditionController extends Controller
$entryData = [];
$entries = $this->ranker->rank('seating', $audition);
$entries->load('student.school');
$seatable = [
'allScored' => true,
'doublersResolved' => true,
];
foreach ($entries as $entry) {
$totalScoreColumn = 'No Score';
$fullyScored = false;
@ -50,6 +53,7 @@ class SeatAuditionController extends Controller
$totalScoreColumn = $entry->score_totals[0] >= 0 ? $entry->score_totals[0] : $entry->score_message;
$fullyScored = $entry->score_totals[0] >= 0;
}
$doublerData = $this->doublerService->entryDoublerData($entry);
$entryData[] = [
'rank' => $entry->rank,
'id' => $entry->id,
@ -58,10 +62,54 @@ class SeatAuditionController extends Controller
'drawNumber' => $entry->draw_number,
'totalScore' => $totalScoreColumn,
'fullyScored' => $fullyScored,
'doubleData' => $this->doublerService->entryDoublerData($entry),
'doubleData' => $doublerData,
];
// 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;
}
}
return view('tabulation.auditionSeating', compact('entryData', 'audition'));
$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;
}
return false;
});
}
return view('tabulation.auditionSeating', compact('entryData', 'audition', 'rightPanel', 'seatableEntries'));
}
protected function pickRightPanel(Audition $audition, array $seatable)
{
if ($audition->hasFlag('seats_published')) {
$rightPanel['view'] = 'tabulation.auditionSeating-show-published-seats';
$rightPanel['data'] = '';
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;
}
}

View File

@ -32,6 +32,7 @@ use App\Services\DoublerService;
use App\Services\DrawService;
use App\Services\EntryService;
use App\Services\ScoreService;
use App\Services\StudentService;
use App\Services\UserService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

View File

@ -40,20 +40,19 @@ class DoublerService
protected function findDoublersForEvent(Event $event, string $mode = 'seating'): array
{
$this->validateEvent($event);
$entries = $event->entries;
$entries = $event->entries()->with('audition')->with('student')->get();
$entries = match ($mode) {
'seating' => $entries->filter(fn ($entry) => $entry->for_seating === 1),
'advancement' => $entries->filter(fn ($entry) => $entry->for_advance === 1),
};
#$entries->load('student.school');
#$entries->load('audition');
$grouped = $entries->groupBy('student_id');
// Filter out student groups with only one entry in the event
$grouped = $grouped->filter(fn ($s) => $s->count() > 1);
$doubler_array = [];
foreach ($grouped as $student_id => $entries) {
$doubler_array[$student_id] = [
'student' => $entries[0]->student,
'student_id' => $student_id,
'entries' => $entries,
];
}
@ -66,15 +65,16 @@ class DoublerService
if (! isset($this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id])) {
return false;
}
return $this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id]['entries'];
}
public function entryDoublerData(Entry $primaryEntry)
{
if (! isset($this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id])) {
if (! isset($this->doublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id])) {
return false;
}
$entries = $this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id]['entries'];
$entries = $this->doublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id]['entries'];
$entryData = collect([]);
/** @var Collection $entries */
foreach ($entries as $entry) {
@ -102,7 +102,7 @@ class DoublerService
'auditionName' => $entry->audition->name,
'status' => $status,
'rank' => $this->entryService->rankOfEntry('seating', $entry),
'unscored_entries' => $entry->audition->unscoredEntries()->count(),
'unscored_entries' => $entry->audition->unscored_entries_count,
'seating_limits' => $limits,
];
}

View File

@ -1,17 +1,20 @@
<x-card.card class="mb-3">
@php
@endphp
<x-card.heading>Seating</x-card.heading>
<div class="py-3 px-1">
<x-form.form method="POST" action="{{ route('tabulation.audition.seat',['audition' => $audition]) }}">
@csrf
@foreach($ensembleLimits as $ensembleLimit)
@foreach($rightPanel['data'] as $ensembleLimit)
@php
$value = $requestedEnsembleAccepts[$ensembleLimit->ensemble->id] ?? $ensembleLimit->maximum_accepted;
//$value = $requestedEnsembleAccepts[$ensembleLimit->ensemble->id] ?? $ensembleLimit['limit'];
$value = $ensembleLimit['limit'];
@endphp
<x-form.field name="ensembleAccept[{{ $ensembleLimit->ensemble->id }}]"
label_text="{{ $ensembleLimit->ensemble->name }} - Max: {{ $ensembleLimit->maximum_accepted }}"
<x-form.field name="ensembleAccept[{{ $ensembleLimit['ensemble']->id }}]"
label_text="{{ $ensembleLimit['ensemble']->name }} - Max: {{ $ensembleLimit['limit'] }}"
type="number"
max="{{ $ensembleLimit->maximum_accepted }}"
max="{{ $ensembleLimit['limit'] }}"
value="{{ $value }}"
class="mb-3"/>
@endforeach

View File

@ -0,0 +1,2 @@
@include('tabulation.auditionSeating-fill-seats-form')
@include('tabulation.auditionSeating-show-proposed-seats')

View File

@ -2,19 +2,20 @@
$seatingProposal = [];
@endphp
@foreach($ensembleLimits as $ensembleLimit)
@foreach($rightPanel['data'] as $ensembleLimit)
<x-card.card class="mb-3">
<x-card.heading>{{ $ensembleLimit->ensemble->name }} - DRAFT</x-card.heading>
<x-card.heading>{{ $ensembleLimit['ensemble']->name }} - DRAFT</x-card.heading>
<x-card.list.body>
@php
$maxAccepted = $requestedEnsembleAccepts[$ensembleLimit->ensemble->id] ?? $ensembleLimit->maximum_accepted;
// $maxAccepted = $requestedEnsembleAccepts[$ensembleLimit->ensemble->id] ?? $ensembleLimit->maximum_accepted;
$maxAccepted = $ensembleLimit['limit'];
@endphp
@for($n=1; $n <= $maxAccepted; $n++)
@php
$entry = $seatableEntries->shift();
if (is_null($entry)) continue;
$seatingProposal[] = [
'ensemble_id' => $ensembleLimit->ensemble->id,
'ensemble_id' => $ensembleLimit['ensemble']->id,
'audition_id' => $audition->id,
'seat' => $n,
'entry_id' => $entry->id,

View File

@ -1,10 +1,10 @@
<x-card.card>
<x-card.heading>Unable to seat this audition</x-card.heading>
@if(! $scoringComplete)
@if(! $rightPanel['data']['allScored'])
<p class="text-sm px-5 py-2">The audition cannot be seated while it has unscored entries.</p>
@endif
@if(! $doublerComplete)
@if(! $rightPanel['data']['doublersResolved'])
<p class="text-sm px-5 py-2">The audition cannot be seated while it has unresolved doublers.</p>
@endif
</x-card.card>

View File

@ -9,6 +9,9 @@
<div class="col-span-3">
@include('tabulation.auditionSeating-results-table')
</div>
<div class="ml-4">
@include($rightPanel['view'])
</div>
{{-- <div class="ml-4">--}}
{{-- @if($audition->hasFlag('seats_published'))--}}
{{-- @include('tabulation.auditionSeating-show-published-seats')--}}

View File

@ -69,5 +69,5 @@ it('identifies a doubler', function () {
$response = get($this->r);
$response->assertOk();
$viewData = $response->viewData('entryData');
expect($viewData[0]['isDoubler'])->toBeTrue();
expect($viewData[0]['doubleData'])->toBeTruthy();
});