Rewrite tabulation #14
|
|
@ -36,7 +36,6 @@ class DoublerDecisionController extends Controller
|
|||
|
||||
}
|
||||
}
|
||||
$this->doublerService->refreshDoublerCache();
|
||||
|
||||
$returnMessage = $entry->student->full_name().' accepted seating in '.$entry->audition->name;
|
||||
|
||||
|
|
@ -52,8 +51,6 @@ class DoublerDecisionController extends Controller
|
|||
|
||||
$entry->addFlag('declined');
|
||||
|
||||
$this->doublerService->refreshDoublerCache();
|
||||
|
||||
$returnMessage = $entry->student->full_name().' declined seating in '.$entry->audition->name;
|
||||
|
||||
return redirect()->back()->with('success', $returnMessage);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use App\Services\AuditionService;
|
|||
use App\Services\DoublerService;
|
||||
use App\Services\EntryService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SeatAuditionController extends Controller
|
||||
{
|
||||
|
|
@ -46,28 +45,6 @@ class SeatAuditionController extends Controller
|
|||
$entries->load('student.school');
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$isDoubler = false;
|
||||
if (array_key_exists($entry->student->id, $doublers)) {
|
||||
$isDoubler = true;
|
||||
$doubleData = [];
|
||||
$doublerEntries = $doublers[$entry->student->id]['entries'];
|
||||
|
||||
foreach ($doublerEntries as $doublerEntry) {
|
||||
$limits = $this->auditionService->getSeatingLimits($doublerEntry->audition);
|
||||
$limits = $limits->reject(function ($lim) {
|
||||
return $lim['limit'] === 0;
|
||||
});
|
||||
$doubleData[] = [
|
||||
'audition' => $doublerEntry->audition,
|
||||
'name' => $doublerEntry->audition->name,
|
||||
'entryId' => $doublerEntry->id,
|
||||
'rank' => $this->entryService->rankOfEntry('seating', $doublerEntry),
|
||||
'limits' => $limits,
|
||||
'status' => 'undecided', // Will be undecided, accepted, or declined
|
||||
'unscored_in_audition' => $doublerEntry->audition->unscoredEntries()->count(),
|
||||
];
|
||||
}
|
||||
}
|
||||
$totalScoreColumn = 'No Score';
|
||||
$fullyScored = false;
|
||||
if ($entry->score_totals) {
|
||||
|
|
@ -82,8 +59,7 @@ class SeatAuditionController extends Controller
|
|||
'drawNumber' => $entry->draw_number,
|
||||
'totalScore' => $totalScoreColumn,
|
||||
'fullyScored' => $fullyScored,
|
||||
'isDoubler' => $isDoubler,
|
||||
'doubleData' => $doubleData ?? [],
|
||||
'doubleData' => $this->doublerService->entryDoublerData($entry),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,15 +98,15 @@ class AuditionService
|
|||
$limits = SeatingLimit::all();
|
||||
|
||||
foreach ($limits as $limit) {
|
||||
$lims[$limit->audition_id][$limit->ensemble_id] = collect([
|
||||
$lims[$limit->audition_id][$limit->ensemble_id] = [
|
||||
'ensemble' => $ensembles->find($limit->ensemble_id),
|
||||
'limit' =>$limit->maximum_accepted,
|
||||
]);
|
||||
];
|
||||
}
|
||||
return collect($lims);
|
||||
return $lims;
|
||||
});
|
||||
|
||||
return collect($allLimits[$audition->id]) ?? [];
|
||||
return $allLimits[$audition->id] ?? [];
|
||||
}
|
||||
|
||||
protected function validateAudition($audition)
|
||||
|
|
|
|||
|
|
@ -6,17 +6,29 @@ use App\Exceptions\TabulationException;
|
|||
use App\Models\Entry;
|
||||
use App\Models\Event;
|
||||
use App\Models\Student;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
/**
|
||||
class DoublerService
|
||||
{
|
||||
protected EntryService $entryService;
|
||||
|
||||
protected AuditionService $auditionService;
|
||||
|
||||
public function __construct(EntryService $entryService, AuditionService $auditionService)
|
||||
{
|
||||
$this->entryService = $entryService;
|
||||
$this->auditionService = $auditionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a collection of doublers for the event in the form of
|
||||
* [studentId => [student=>student, entries=>[entries]]
|
||||
*/
|
||||
class DoublerService
|
||||
{
|
||||
public function doublersForEvent(Event $event, string $mode = 'seating')
|
||||
{
|
||||
$cacheKey = 'event'.$event->id.'doublers-'.$mode;
|
||||
|
||||
return Cache::remember($cacheKey, 60, function () use ($event, $mode) {
|
||||
return $this->findDoublersForEvent($event, $mode);
|
||||
});
|
||||
|
|
@ -25,7 +37,7 @@ class DoublerService
|
|||
/**
|
||||
* @throws TabulationException
|
||||
*/
|
||||
protected function findDoublersForEvent(Event $event, string $mode): array
|
||||
protected function findDoublersForEvent(Event $event, string $mode = 'seating'): array
|
||||
{
|
||||
$this->validateEvent($event);
|
||||
$entries = $event->entries;
|
||||
|
|
@ -49,6 +61,59 @@ class DoublerService
|
|||
return $doubler_array;
|
||||
}
|
||||
|
||||
public function entryDoublerData(Entry $primaryEntry)
|
||||
{
|
||||
if (! isset($this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id])) {
|
||||
return false;
|
||||
}
|
||||
$entries = $this->findDoublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id]['entries'];
|
||||
$entryData = collect([]);
|
||||
/** @var Collection $entries */
|
||||
foreach ($entries as $entry) {
|
||||
$status = 'undecided';
|
||||
if ($entry->hasFlag('declined')) {
|
||||
$status = 'declined';
|
||||
}
|
||||
if ($entry->hasFlag('no_show')) {
|
||||
$status = 'no_show';
|
||||
}
|
||||
|
||||
$lims = $this->auditionService->getSeatingLimits($entry->audition);
|
||||
$limits = [];
|
||||
foreach ($lims as $lim) {
|
||||
$limits[] = [
|
||||
'ensemble_name' => $lim['ensemble']->name,
|
||||
'accepts' => $lim['limit'],
|
||||
'ensemble' => $lim['ensemble'],
|
||||
];
|
||||
}
|
||||
|
||||
$entryData[$entry->id] = [
|
||||
'entry' => $entry,
|
||||
'audition' => $entry->audition,
|
||||
'auditionName' => $entry->audition->name,
|
||||
'status' => $status,
|
||||
'rank' => $this->entryService->rankOfEntry('seating', $entry),
|
||||
'unscored_entries' => $entry->audition->unscoredEntries()->count(),
|
||||
'seating_limits' => $limits,
|
||||
];
|
||||
}
|
||||
// find out how many items in the collection $entryData have a status of 'undecided'
|
||||
$undecided_count = $entryData->filter(fn ($entry) => $entry['status'] === 'undecided')->count();
|
||||
// if $undecided_count is 1 set the item where status is 'undecided' to 'accepted'
|
||||
if ($undecided_count === 1) {
|
||||
$entryData->transform(function ($entry) {
|
||||
if ($entry['status'] === 'undecided') {
|
||||
$entry['status'] = 'accepted';
|
||||
}
|
||||
|
||||
return $entry;
|
||||
});
|
||||
}
|
||||
|
||||
return $entryData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TabulationException
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ class EntryService
|
|||
{
|
||||
$ranker = App::make(RankAuditionEntries::class);
|
||||
$rankings = $ranker->rank($mode, $entry->audition);
|
||||
$rankedEntry = $rankings->find($entry->id);
|
||||
if (isset($rankedEntry->score_message)) {
|
||||
return $rankedEntry->score_message;
|
||||
}
|
||||
return $rankings->find($entry->id)->rank ?? 'No Rank';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
<li class="pb-2 pt-0 px-0 my-2 rounded-xl border border-gray-200 max-w-xs" x-data="{ open: {{ $isopen ? 'true':'false' }} }">
|
||||
<div class="flex items-start gap-x-3 bg-gray-100 px-3 py-2 rounded-t-xl" >
|
||||
<p class="text-sm font-semibold leading-6 text-gray-900">
|
||||
{{-- TODO put in link --}}
|
||||
<a href="{{ route('seating.audition', $double['audition']) }}">
|
||||
{{ $double['name'] }} - {{ $double['status'] }}
|
||||
{{ $double['auditionName'] }} - {{ $double['status'] }}
|
||||
</a>
|
||||
</p>
|
||||
<div class="w-full flex justify-end" >
|
||||
|
|
@ -21,26 +20,23 @@
|
|||
<div class="grid grid-cols-4" x-show="open">
|
||||
<div class="mt-1 px-3 text-xs leading-5 text-gray-500 col-span-3">
|
||||
<ul>
|
||||
<li class="flex items-center gap-x-2">
|
||||
<li class="">
|
||||
<p class="whitespace-nowrap">Ranked {{ $double['rank'] }}</p>
|
||||
<svg viewBox="0 0 2 2" class="h-0.5 w-0.5 fill-current">
|
||||
<circle cx="1" cy="1" r="1" />
|
||||
</svg>
|
||||
<p class="truncate">{{ $double['unscored_in_audition'] }} Unscored</p>
|
||||
<p class="truncate">{{ $double['unscored_entries'] }} Unscored</p>
|
||||
</li>
|
||||
@foreach($double['limits'] as $limit)
|
||||
<li>{{$limit['ensemble']->name}} accepts {{ $limit['limit'] }}</li>
|
||||
@foreach($double['seating_limits'] as $limit)
|
||||
<li>{{$limit['ensemble_name']}} accepts {{ $limit['accepts'] }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-end gap-y-1 pt-1">
|
||||
@if ($double['status'] == 'undecided')
|
||||
<form method="POST" action="{{ route('doubler.accept',['entry'=>$double['entryId']]) }}">
|
||||
<form method="POST" action="{{ route('doubler.accept',['entry'=>$double['entry']]) }}">
|
||||
@csrf
|
||||
<button class="{{ $doublerButtonClasses }}">Accept</button>
|
||||
</form>
|
||||
<form method="POST" action="{{ route('doubler.decline',['entry'=>$double['entryId']]) }}">
|
||||
<form method="POST" action="{{ route('doubler.decline',['entry'=>$double['entry']]) }}">
|
||||
@csrf
|
||||
<button class="{{ $doublerButtonClasses }}">Decline</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<span class="text-xs text-gray-400">{{ $entry['schoolName'] }}</span>
|
||||
</x-table.td>
|
||||
<x-table.td class="!py-0">
|
||||
@if($entry['isDoubler'])
|
||||
@if($entry['doubleData'])
|
||||
@include('tabulation.auditionSeating-doubler-block')
|
||||
{{-- DOUBLER<br>--}}
|
||||
{{-- @foreach($entry['doubleData'] as $double)--}}
|
||||
|
|
|
|||
|
|
@ -23,38 +23,37 @@ it('throws an error if an invalid event is provided', function () {
|
|||
it('returns doublers for an event', function () {
|
||||
$concertEvent = Event::factory()->create(['name' => 'Concert Band', 'id' => 1000]);
|
||||
$jazzEvent = Event::factory()->create(['name' => 'Jazz Band', 'id' => 1001]);
|
||||
|
||||
$auditionAS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1000, 'name' => 'Alto Sax', 'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1000,
|
||||
]);
|
||||
$auditionTS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1000, 'name' => 'Tenor Sax', 'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1001,
|
||||
]);
|
||||
$auditionBS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1000, 'name' => 'Baritone Sax', 'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1002,
|
||||
]);
|
||||
$auditionCL = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1000, 'name' => 'Clarinet', 'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1003,
|
||||
]);
|
||||
$auditionBCL = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1000, 'name' => 'Bass Clarinet',
|
||||
'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1004,
|
||||
]);
|
||||
$auditionJAS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1001, 'name' => 'Jazz Alto', 'minimum_grade' => 7,
|
||||
'maximum_grade' => 12, 'id' => 1005,
|
||||
]);
|
||||
$auditionJTS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1001, 'name' => 'Jazz Tenor', 'minimum_grade' => 7,
|
||||
'maximum_grade' => 12, 'id' => 1006,
|
||||
]);
|
||||
$auditionJBS = Audition::factory()->create([
|
||||
Audition::factory()->create([
|
||||
'event_id' => 1001, 'name' => 'Jazz Baritone',
|
||||
'minimum_grade' => 7, 'maximum_grade' => 12, 'id' => 1007,
|
||||
]);
|
||||
$allSaxDude = Student::factory()->create(['grade' => 11, 'id' => 1000]);
|
||||
$clarinetGal = Student::factory()->create(['grade' => 9, 'id' => 1001]);
|
||||
$justAlto = Student::factory()->create(['grade' => 9, 'id' => 1002]);
|
||||
Student::factory()->create(['grade' => 9, 'id' => 1001]);
|
||||
Student::factory()->create(['grade' => 9, 'id' => 1002]);
|
||||
Entry::create(['student_id' => 1000, 'audition_id' => 1000]);
|
||||
Entry::create(['student_id' => 1000, 'audition_id' => 1001]);
|
||||
Entry::create(['student_id' => 1000, 'audition_id' => 1002]);
|
||||
|
|
@ -67,13 +66,13 @@ it('returns doublers for an event', function () {
|
|||
Entry::create(['student_id' => 1002, 'audition_id' => 1005]);
|
||||
|
||||
$return = $this->doublerService->doublersForEvent($concertEvent);
|
||||
expect(count($return))->toBe(2);
|
||||
expect($return[1000]['student']->id)->toBe($allSaxDude->id);
|
||||
expect($return[1000]['entries']->count())->toBe(3);
|
||||
expect($return[1001]['entries']->count())->toBe(2);
|
||||
expect(count($return))->toBe(2)
|
||||
->and($return[1000]['student']->id)->toBe($allSaxDude->id)
|
||||
->and($return[1000]['entries']->count())->toBe(3)
|
||||
->and($return[1001]['entries']->count())->toBe(2);
|
||||
assertArrayNotHasKey(1002, $return);
|
||||
$return = $this->doublerService->doublersForEvent($jazzEvent);
|
||||
expect(count($return))->toBe(1);
|
||||
expect($return[1000]['student']->id)->toBe($allSaxDude->id);
|
||||
expect($return[1000]['entries']->count())->toBe(3);
|
||||
expect(count($return))->toBe(1)
|
||||
->and($return[1000]['student']->id)->toBe($allSaxDude->id)
|
||||
->and($return[1000]['entries']->count())->toBe(3);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue