126 lines
4.3 KiB
PHP
126 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Entry;
|
|
use App\Models\Student;
|
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class DoublerService
|
|
{
|
|
protected $doublersCacheKey = 'doublers';
|
|
|
|
protected $auditionService;
|
|
|
|
protected $tabulationService;
|
|
|
|
protected $seatingService;
|
|
|
|
/**
|
|
* Create a new class instance.
|
|
*/
|
|
public function __construct(AuditionService $auditionService, TabulationService $tabulationService, SeatingService $seatingService)
|
|
{
|
|
$this->auditionService = $auditionService;
|
|
$this->tabulationService = $tabulationService;
|
|
$this->seatingService = $seatingService;
|
|
}
|
|
|
|
/**
|
|
* Returns a collection of students that have more than one entry
|
|
*/
|
|
public function getDoublers(): \Illuminate\Database\Eloquent\Collection
|
|
{
|
|
// TODO creating or destroying an entry should refresh the doubler cache
|
|
// TODO needs to split by event so that a doubler may enter jazz and concert events for example
|
|
$doublers = Cache::remember($this->doublersCacheKey, 60, function () {
|
|
return Student::withCount(['entries' => function (Builder $query) {
|
|
$query->where('for_seating', true);
|
|
}])
|
|
->with(['entries' => function (Builder $query) {
|
|
$query->where('for_seating', true);
|
|
}])
|
|
->havingRaw('entries_count > ?', [1])
|
|
->get();
|
|
});
|
|
|
|
return $doublers;
|
|
}
|
|
|
|
public function refreshDoublerCache()
|
|
{
|
|
Cache::forget($this->doublersCacheKey);
|
|
$this->getDoublers();
|
|
}
|
|
|
|
/**
|
|
* Returns an array of information about each entry for a specific doubler. Info for each entry includes
|
|
* entryID
|
|
* auditionID
|
|
* auditionName
|
|
* rank => This student's rank in the given audition
|
|
* unscored => How many entries remain to be scored in this audition
|
|
* limits => acceptance limits for this audition
|
|
* status => accepted, declined, or undecided
|
|
*
|
|
* @param int $studentId The ID of the doubler
|
|
*/
|
|
public function getDoublerInfo($studentId): array
|
|
{
|
|
$doubler = $this->getDoublers()->firstWhere('id', $studentId);
|
|
|
|
// Split $doubler->entries into two arrays based on the result of hasFlag('declined')
|
|
$undecidedEntries = $doubler->entries->filter(function ($entry) {
|
|
return ! $entry->hasFlag('declined');
|
|
});
|
|
$acceptedEntry = null;
|
|
if ($undecidedEntries->count() == 1) {
|
|
$acceptedEntry = $undecidedEntries->first();
|
|
}
|
|
// TODO can I rewrite this?
|
|
|
|
// When getting a doubler we need to know
|
|
// 1) What their entries are
|
|
// 2) For each audition they're entered in, what is their rank
|
|
// 3) For each audition they're entered in, how many entries are unscored
|
|
// 4) How many are accepted on that instrument
|
|
// 5) Status - accepted, declined or undecided
|
|
|
|
$info = [];
|
|
|
|
foreach ($doubler->entries as $entry) {
|
|
if ($entry->hasFlag('declined')) {
|
|
$status = 'declined';
|
|
} elseif ($entry === $acceptedEntry) {
|
|
$status = 'accepted';
|
|
} else {
|
|
$status = 'undecided';
|
|
}
|
|
$info[$entry->id] = [
|
|
'entryID' => $entry->id,
|
|
'auditionID' => $entry->audition_id,
|
|
'auditionName' => $this->auditionService->getAudition($entry->audition_id)->name,
|
|
'rank' => $this->tabulationService->entryRank($entry),
|
|
'unscored' => $this->tabulationService->remainingEntriesForAudition($entry->audition_id),
|
|
'limits' => $this->seatingService->getLimitForAudition($entry->audition_id),
|
|
'status' => $status,
|
|
];
|
|
$entry->audition = $this->auditionService->getAudition($entry->audition_id);
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* Checks if a student is a doubler based on the given student ID
|
|
*
|
|
* @param int $studentId The ID of the student to check
|
|
* @return bool Returns true if the student is a doubler, false otherwise
|
|
*/
|
|
public function studentIsDoubler($studentId): bool
|
|
{
|
|
return $this->getDoublers()->contains('id', $studentId);
|
|
}
|
|
}
|