135 lines
4.5 KiB
PHP
135 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
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]]
|
|
*/
|
|
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);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @throws TabulationException
|
|
*/
|
|
protected function findDoublersForEvent(Event $event, string $mode = 'seating'): array
|
|
{
|
|
$this->validateEvent($event);
|
|
$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),
|
|
};
|
|
|
|
$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_id' => $student_id,
|
|
'entries' => $entries,
|
|
];
|
|
}
|
|
|
|
return $doubler_array;
|
|
}
|
|
|
|
public function simpleDoubleInfo(Entry $primaryEntry)
|
|
{
|
|
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->doublersForEvent($primaryEntry->audition->event)[$primaryEntry->student_id])) {
|
|
return false;
|
|
}
|
|
$entries = $this->doublersForEvent($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->unscored_entries_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
|
|
*/
|
|
protected function validateEvent(Event $event)
|
|
{
|
|
if (! $event->exists) {
|
|
throw new TabulationException('Invalid event provided');
|
|
}
|
|
}
|
|
}
|