auditionadmin/app/Services/DoublerService.php

114 lines
3.8 KiB
PHP

<?php
namespace App\Services;
use App\Models\Entry;
use App\Models\Student;
use Illuminate\Support\Facades\Cache;
class DoublerService
{
protected $doublersCacheKey = 'doublers';
protected $auditionCacheService;
protected $tabulationService;
protected $seatingService;
/**
* Create a new class instance.
*/
public function __construct(AuditionCacheService $auditionCacheService, TabulationService $tabulationService, SeatingService $seatingService)
{
$this->auditionCacheService = $auditionCacheService;
$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
return Cache::remember($this->doublersCacheKey, 60, function () {
return Student::withCount('entries')
->with('entries')
->havingRaw('entries_count > ?', [1])
->get();
});
}
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
* auditionID
* auditionName
* rank => This student's rank in the given audition
* unscored => How many entries remain to be scored in this audition
*
* @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] = [
'auditionID' => $entry->audition_id,
'auditionName' => $this->auditionCacheService->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->auditionCacheService->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);
}
}