175 lines
6.2 KiB
PHP
175 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Entry;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Session;
|
|
|
|
class TabulationService
|
|
{
|
|
protected AuditionCacheService $auditionCacheService;
|
|
|
|
protected EntryCacheService $entryCacheService;
|
|
|
|
protected ScoreService $scoreService;
|
|
|
|
/**
|
|
* Create a new class instance.
|
|
*/
|
|
public function __construct(
|
|
AuditionCacheService $scoringGuideCacheService,
|
|
ScoreService $scoreService,
|
|
EntryCacheService $entryCacheService)
|
|
{
|
|
$this->auditionCacheService = $scoringGuideCacheService;
|
|
$this->scoreService = $scoreService;
|
|
$this->entryCacheService = $entryCacheService;
|
|
}
|
|
|
|
/**
|
|
* Returns the rank of the entry in its audition
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function entryRank(Entry $entry)
|
|
{
|
|
return $this->auditionEntries($entry->audition_id)[$entry->id]->rank;
|
|
}
|
|
|
|
/**
|
|
* Returns a collection of entries including their calculated final_score_array and ranked
|
|
* based upon their scores.
|
|
*
|
|
* @return \Illuminate\Support\Collection|mixed
|
|
*/
|
|
public function auditionEntries(int $auditionId)
|
|
{
|
|
static $cache = [];
|
|
if (isset($cache[$auditionId])) {
|
|
return $cache[$auditionId];
|
|
}
|
|
|
|
$audition = $this->auditionCacheService->getAudition($auditionId);
|
|
$entries = $this->entryCacheService->getEntriesForAudition($auditionId);
|
|
$this->scoreService->calculateScoresForAudition($auditionId);
|
|
|
|
foreach ($entries as $entry) {
|
|
$entry->final_score_array = $this->scoreService->entryTotalScores($entry);
|
|
$entry->scoring_complete = ($this->scoreService->entryScoreSheetCounts()[$entry->id] == $audition->judges_count);
|
|
}
|
|
// Sort the array $entries by the first element in the final_score_array on each entry, then by the second element in that array continuing through each element in the final_score_array for each entry
|
|
$entries = $entries->sort(function ($a, $b) {
|
|
for ($i = 0; $i < count($a->final_score_array); $i++) {
|
|
if ($a->final_score_array[$i] != $b->final_score_array[$i]) {
|
|
return $b->final_score_array[$i] > $a->final_score_array[$i] ? 1 : -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
|
|
//TODO verify this actually sorts by subscores correctly
|
|
$n = 1;
|
|
/** @var Entry $entry */
|
|
foreach ($entries as $entry) {
|
|
if (! $entry->hasFlag('declined')) {
|
|
$entry->rank = $n;
|
|
$n++;
|
|
} else {
|
|
$entry->rank = $n.' - declined';
|
|
}
|
|
}
|
|
$cache[$auditionId] = $entries->keyBy('id');
|
|
|
|
return $entries->keyBy('id');
|
|
}
|
|
|
|
public function entryScoreSheetsAreValid(Entry $entry): bool
|
|
{
|
|
//TODO consider making this move the invalid score to another database for further investigation
|
|
$validJudges = $this->auditionCacheService->getAudition($entry->audition_id)->judges;
|
|
foreach ($entry->scoreSheets as $sheet) {
|
|
if (! $validJudges->contains($sheet->user_id)) {
|
|
$invalidJudge = User::find($sheet->user_id);
|
|
Session::flash('error', 'Invalid scores for entry '.$entry->id.' exist from '.$invalidJudge->full_name());
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of un-scored entries for the audition with the given ID.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function remainingEntriesForAudition($auditionId, $mode = 'seating')
|
|
{
|
|
$audition = $this->getAuditionsWithStatus($mode)[$auditionId];
|
|
|
|
switch ($mode) {
|
|
case 'seating':
|
|
return $audition->seating_entries_count - $audition->scored_entries_count;
|
|
case 'advancement':
|
|
return $audition->advancement_entries_count - $audition->scored_entries_count;
|
|
}
|
|
return $audition->entries_count - $audition->scored_entries_count;
|
|
}
|
|
|
|
/**
|
|
* Get the array of all auditions from the cache. For each one, set a property
|
|
* scored_entries_count that indicates the number of entries for that audition that
|
|
* have a number of score sheets equal to the number of judges for that audition.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function getAuditionsWithStatus($mode = 'seating')
|
|
{
|
|
return Cache::remember('auditionsWithStatus', 30, function () use ($mode) {
|
|
|
|
// Retrieve auditions from the cache and load entry IDs
|
|
$auditions = $this->auditionCacheService->getAuditions();
|
|
|
|
|
|
// Iterate over the auditions and calculate the scored_entries_count
|
|
foreach ($auditions as $audition) {
|
|
$scored_entries_count = 0;
|
|
$entries_to_check = $this->entryCacheService->getEntriesForAudition($audition->id);
|
|
|
|
switch ($mode) {
|
|
case 'seating':
|
|
$entries_to_check = $entries_to_check->filter(function ($entry) {
|
|
return $entry->for_seating;
|
|
});
|
|
$auditions = $auditions->filter(function ($audition) {
|
|
return $audition->for_seating;
|
|
});
|
|
break;
|
|
case 'advancement':
|
|
$entries_to_check = $entries_to_check->filter(function ($entry) {
|
|
return $entry->for_advancement;
|
|
});
|
|
$auditions = $auditions->filter(function ($audition) {
|
|
return $audition->for_advancement;
|
|
});
|
|
break;
|
|
}
|
|
|
|
foreach ($entries_to_check as $entry) {
|
|
if ($this->scoreService->entryScoreSheetCounts()[$entry->id] - $audition->judges_count == 0) {
|
|
$scored_entries_count++;
|
|
}
|
|
}
|
|
|
|
$audition->scored_entries_count = $scored_entries_count;
|
|
}
|
|
|
|
return $auditions;
|
|
});
|
|
}
|
|
}
|