Correct error in entryScoreSheetCounts metho of ScoreService
This commit is contained in:
parent
cc101a29bf
commit
bf3313bf30
|
|
@ -8,12 +8,15 @@ use App\Models\ScoringGuide;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
use function array_unshift;
|
use function array_unshift;
|
||||||
|
|
||||||
class ScoreService
|
class ScoreService
|
||||||
{
|
{
|
||||||
protected $auditionCache;
|
protected $auditionCache;
|
||||||
|
|
||||||
protected $entryCache;
|
protected $entryCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new class instance.
|
* Create a new class instance.
|
||||||
*/
|
*/
|
||||||
|
|
@ -25,64 +28,69 @@ class ScoreService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache all scoring guides
|
* Cache all scoring guides
|
||||||
* @return \Illuminate\Database\Eloquent\Collection
|
|
||||||
*/
|
*/
|
||||||
public function getScoringGuides(): \Illuminate\Database\Eloquent\Collection
|
public function getScoringGuides(): \Illuminate\Database\Eloquent\Collection
|
||||||
{
|
{
|
||||||
$cacheKey = 'scoringGuides';
|
$cacheKey = 'scoringGuides';
|
||||||
return Cache::remember($cacheKey, 3600, fn() => ScoringGuide::with('subscores')->withCount('subscores')->get());
|
|
||||||
|
return Cache::remember($cacheKey, 3600, fn () => ScoringGuide::with('subscores')->withCount('subscores')->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a single scoring guide from the cache
|
* Retrieve a single scoring guide from the cache
|
||||||
* @param $id
|
|
||||||
* @return ScoringGuide
|
|
||||||
*/
|
*/
|
||||||
public function getScoringGuide($id): ScoringGuide
|
public function getScoringGuide($id): ScoringGuide
|
||||||
{
|
{
|
||||||
return $this->getScoringGuides()->find($id);
|
return $this->getScoringGuides()->find($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the scoring guide cache
|
* Clear the scoring guide cache
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function clearScoringGuideCache(): void
|
public function clearScoringGuideCache(): void
|
||||||
{
|
{
|
||||||
Cache::forget('scoringGuides');
|
Cache::forget('scoringGuides');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array where each key is an entry id and the value is the number
|
* Returns an array where each key is an entry id and the value is the number
|
||||||
* of score sheets assigned to that entry.
|
* of score sheets assigned to that entry.
|
||||||
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function entryScoreSheetCounts()
|
public function entryScoreSheetCounts()
|
||||||
{
|
{
|
||||||
$cacheKey = 'entryScoreSheetCounts';
|
$cacheKey = 'entryScoreSheetCounts';
|
||||||
return Cache::remember($cacheKey, 10, function() {
|
|
||||||
|
return Cache::remember($cacheKey, 10, function () {
|
||||||
// For each Entry get the number of ScoreSheets associated with it
|
// For each Entry get the number of ScoreSheets associated with it
|
||||||
$entryScoreSheetCounts = ScoreSheet::select('entry_id', DB::raw('count(*) as count'))
|
$scoreSheetCountsByEntry = ScoreSheet::select('entry_id', DB::raw('count(*) as count'))
|
||||||
->groupBy('entry_id')
|
->groupBy('entry_id')
|
||||||
->get()
|
->get()
|
||||||
->pluck('count','entry_id');
|
->pluck('count', 'entry_id');
|
||||||
|
|
||||||
|
$entryScoreSheetCounts = [];
|
||||||
|
$entries = $this->entryCache->getAllEntries();
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$entryScoreSheetCounts[$entry->id] = $scoreSheetCountsByEntry[$entry->id] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
return $entryScoreSheetCounts;
|
return $entryScoreSheetCounts;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get final scores array for the requested entry. The first element is the total score. The following elements are sums
|
* Get final scores array for the requested entry. The first element is the total score. The following elements are sums
|
||||||
* of each subscore in tiebreaker order
|
* of each subscore in tiebreaker order
|
||||||
* @param Entry $entry
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function entryTotalScores(Entry $entry)
|
public function entryTotalScores(Entry $entry)
|
||||||
{
|
{
|
||||||
$cacheKey = 'entry' . $entry->id . 'totalScores';
|
$cacheKey = 'entry'.$entry->id.'totalScores';
|
||||||
|
|
||||||
return Cache::remember($cacheKey, 3600, function () use ($entry) {
|
return Cache::remember($cacheKey, 3600, function () use ($entry) {
|
||||||
return $this->calculateFinalScoreArray($entry->audition->scoring_guide_id, $entry->scoreSheets);
|
return $this->calculateFinalScoreArray($entry->audition->scoring_guide_id, $entry->scoreSheets);
|
||||||
});
|
});
|
||||||
|
|
@ -90,22 +98,24 @@ class ScoreService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate and cache scores for all entries for the provided audition ID
|
* Calculate and cache scores for all entries for the provided audition ID
|
||||||
* @param $auditionId
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function calculateScoresForAudition($auditionId)
|
public function calculateScoresForAudition($auditionId)
|
||||||
{
|
{
|
||||||
$audition = $this->auditionCache->getAudition($auditionId);
|
$audition = $this->auditionCache->getAudition($auditionId);
|
||||||
$scoringGuideId = $audition->scoring_guide_id;
|
$scoringGuideId = $audition->scoring_guide_id;
|
||||||
// $entries = Entry::where('audition_id',$auditionId)->with('scoreSheets')->get();
|
// $entries = Entry::where('audition_id',$auditionId)->with('scoreSheets')->get();
|
||||||
$entries = $this->entryCache->getEntriesForAudition($auditionId);
|
$entries = $this->entryCache->getEntriesForAudition($auditionId);
|
||||||
$entries->load('scoreSheets'); // TODO Cache this somehow, it's expensive and repetitive on the seating page
|
$entries->load('scoreSheets'); // TODO Cache this somehow, it's expensive and repetitive on the seating page
|
||||||
|
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$cacheKey = 'entry' . $entry->id . 'totalScores';
|
$cacheKey = 'entry'.$entry->id.'totalScores';
|
||||||
if (Cache::has($cacheKey)) continue;
|
if (Cache::has($cacheKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$thisTotalScore = $this->calculateFinalScoreArray($scoringGuideId, $entry->scoreSheets);
|
$thisTotalScore = $this->calculateFinalScoreArray($scoringGuideId, $entry->scoreSheets);
|
||||||
Cache::put($cacheKey,$thisTotalScore,3600);
|
Cache::put($cacheKey, $thisTotalScore, 3600);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,15 +127,14 @@ class ScoreService
|
||||||
|
|
||||||
public function clearEntryTotalScoresCache($entryId)
|
public function clearEntryTotalScoresCache($entryId)
|
||||||
{
|
{
|
||||||
$cacheKey = 'entry' . $entryId . 'totalScores';
|
$cacheKey = 'entry'.$entryId.'totalScores';
|
||||||
Cache::forget($cacheKey);
|
Cache::forget($cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearAllCachedTotalScores()
|
public function clearAllCachedTotalScores()
|
||||||
{
|
{
|
||||||
foreach ($this->entryCache->getAllEntries() as $entry)
|
foreach ($this->entryCache->getAllEntries() as $entry) {
|
||||||
{
|
$cacheKey = 'entry'.$entry->id.'totalScores';
|
||||||
$cacheKey = 'entry' . $entry->id . 'totalScores';
|
|
||||||
Cache::forget($cacheKey);
|
Cache::forget($cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,9 +143,6 @@ class ScoreService
|
||||||
* Calculate final score using the provided scoring guide and score sheets. Returns an array of scores
|
* Calculate final score using the provided scoring guide and score sheets. Returns an array of scores
|
||||||
* The first element is the total score. The following elements are the sum of each subscore
|
* The first element is the total score. The following elements are the sum of each subscore
|
||||||
* in tiebreaker order.
|
* in tiebreaker order.
|
||||||
* @param $scoringGuideId
|
|
||||||
* @param array|Collection $scoreSheets
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function calculateFinalScoreArray($scoringGuideId, array|Collection $scoreSheets): array
|
public function calculateFinalScoreArray($scoringGuideId, array|Collection $scoreSheets): array
|
||||||
{
|
{
|
||||||
|
|
@ -148,18 +154,18 @@ class ScoreService
|
||||||
|
|
||||||
$ignoredSubscores = []; // This will be subscores not used for seating
|
$ignoredSubscores = []; // This will be subscores not used for seating
|
||||||
|
|
||||||
|
|
||||||
// Init final scores array
|
// Init final scores array
|
||||||
$finalScoresArray = [];
|
$finalScoresArray = [];
|
||||||
foreach ($subscores as $subscore) {
|
foreach ($subscores as $subscore) {
|
||||||
if (! $subscore->for_seating) { // Ignore scores that are not for seating
|
if (! $subscore->for_seating) { // Ignore scores that are not for seating
|
||||||
$ignoredSubscores[] = $subscore->id;
|
$ignoredSubscores[] = $subscore->id;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$finalScoresArray[$subscore->id] = 0;
|
$finalScoresArray[$subscore->id] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($scoreSheets as $sheet) {
|
foreach ($scoreSheets as $sheet) {
|
||||||
foreach ($sheet->subscores as $ss) {
|
foreach ($sheet->subscores as $ss) {
|
||||||
if (in_array($ss['subscore_id'], $ignoredSubscores)) { // Ignore scores that are not for seating
|
if (in_array($ss['subscore_id'], $ignoredSubscores)) { // Ignore scores that are not for seating
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -179,14 +185,15 @@ class ScoreService
|
||||||
$totalWeight += $subscore->weight;
|
$totalWeight += $subscore->weight;
|
||||||
}
|
}
|
||||||
$totalScore = ($totalScore / $totalWeight);
|
$totalScore = ($totalScore / $totalWeight);
|
||||||
array_unshift($finalScoresArray,$totalScore);
|
array_unshift($finalScoresArray, $totalScore);
|
||||||
|
|
||||||
return $finalScoresArray;
|
return $finalScoresArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that the judge on the score sheet is actually assigned to judge
|
* Validate that the judge on the score sheet is actually assigned to judge
|
||||||
* then entry
|
* then entry
|
||||||
* @param ScoreSheet $sheet
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function validateScoreSheet(ScoreSheet $sheet)
|
public function validateScoreSheet(ScoreSheet $sheet)
|
||||||
|
|
@ -196,14 +203,12 @@ class ScoreService
|
||||||
$audition = $this->auditionCache->getAudition($entry->audition_id);
|
$audition = $this->auditionCache->getAudition($entry->audition_id);
|
||||||
$validJudges = $audition->judges;
|
$validJudges = $audition->judges;
|
||||||
// send a laravel flash message with an error if the $sheet->user_id is not in the collection $validJudges
|
// send a laravel flash message with an error if the $sheet->user_id is not in the collection $validJudges
|
||||||
if (!$validJudges->contains('id', $sheet->user_id)) {
|
if (! $validJudges->contains('id', $sheet->user_id)) {
|
||||||
session()->flash('error', 'Entry ID ' . $sheet->entry_id . ' has an invalid score entered by ' . $sheet->judge->full_name());
|
session()->flash('error', 'Entry ID '.$sheet->entry_id.' has an invalid score entered by '.$sheet->judge->full_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if $sheet->user_id is in the collection $validJudges, return false if not, true if it is
|
// check if $sheet->user_id is in the collection $validJudges, return false if not, true if it is
|
||||||
return $validJudges->contains('id', $sheet->user_id);
|
return $validJudges->contains('id', $sheet->user_id);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class TabulationService
|
||||||
|
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$entry->final_score_array = $this->scoreService->entryTotalScores($entry);
|
$entry->final_score_array = $this->scoreService->entryTotalScores($entry);
|
||||||
$entry->scoring_complete = $this->scoreService->entryScoreSheetCounts()[$entry->id] ?? $audition->judges_count == 0;
|
$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
|
// 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) {
|
$entries = $entries->sort(function ($a, $b) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<x-card.card class="px-3">
|
||||||
|
<x-table.table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th>Rank</x-table.th>
|
||||||
|
<x-table.th>ID</x-table.th>
|
||||||
|
<x-table.th>Draw #</x-table.th>
|
||||||
|
<x-table.th>Student Name</x-table.th>
|
||||||
|
<x-table.th>Doubler</x-table.th>
|
||||||
|
{{-- @foreach($judges as $judge)--}}
|
||||||
|
{{-- <x-table.th>{{ $judge->short_name() }}</x-table.th>--}}
|
||||||
|
{{-- @endforeach--}}
|
||||||
|
<x-table.th>Total Score</x-table.th>
|
||||||
|
<x-table.th>All Scores?</x-table.th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<x-table.body>
|
||||||
|
@foreach($entries as $entry)
|
||||||
|
<tr>
|
||||||
|
<x-table.td>{{ $entry->rank }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->id }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->draw_number }}</x-table.td>
|
||||||
|
<x-table.td>
|
||||||
|
<span>{{ $entry->student->full_name() }}, </span>
|
||||||
|
<span class="text-xs text-gray-400">{{ $entry->student->school->name }}</span>
|
||||||
|
</x-table.td>
|
||||||
|
<x-table.td class="!py-0">
|
||||||
|
@if($doublerService->studentIsDoubler($entry->student_id))
|
||||||
|
@include('tabulation.doubler-block')
|
||||||
|
@endif
|
||||||
|
</x-table.td>
|
||||||
|
<x-table.td>{{ number_format($entry->final_score_array[0] ?? 0,4) }}</x-table.td>
|
||||||
|
<x-table.td>
|
||||||
|
@if($entry->scoring_complete)
|
||||||
|
<x-icons.checkmark color="green"/>
|
||||||
|
@endif
|
||||||
|
</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</x-table.table>
|
||||||
|
|
||||||
|
</x-card.card>
|
||||||
|
|
@ -1,50 +1,28 @@
|
||||||
@inject('doublerService','App\Services\DoublerService')
|
@inject('doublerService','App\Services\DoublerService')
|
||||||
|
@php($blockSeating = [])
|
||||||
<x-layout.app>
|
<x-layout.app>
|
||||||
<x-slot:page_title>Audition Seating - {{ $audition->name }}</x-slot:page_title>
|
<x-slot:page_title>Audition Seating - {{ $audition->name }}</x-slot:page_title>
|
||||||
|
<div class="grid grid-cols-4"></div>
|
||||||
|
<div class="grid grid-cols-4">
|
||||||
|
<div class="col-span-3">
|
||||||
|
@include('tabulation.audition-results-table')
|
||||||
|
</div>
|
||||||
|
<div class="ml-4">
|
||||||
|
<x-card.card>
|
||||||
|
<x-card.heading>
|
||||||
|
Seating Form
|
||||||
|
</x-card.heading>
|
||||||
|
<div class="pl-3">
|
||||||
|
|
||||||
<x-card.card class="px-3">
|
@foreach($entries as $entry)
|
||||||
<x-table.table>
|
{{ dump($entry) }}
|
||||||
<thead>
|
@endforeach
|
||||||
<tr>
|
</div>
|
||||||
<x-table.th>Rank</x-table.th>
|
</x-card.card>
|
||||||
<x-table.th>ID</x-table.th>
|
</div>
|
||||||
<x-table.th>Draw #</x-table.th>
|
</div>
|
||||||
<x-table.th>Student Name</x-table.th>
|
|
||||||
<x-table.th>Doubler</x-table.th>
|
|
||||||
{{-- @foreach($judges as $judge)--}}
|
|
||||||
{{-- <x-table.th>{{ $judge->short_name() }}</x-table.th>--}}
|
|
||||||
{{-- @endforeach--}}
|
|
||||||
<x-table.th>Total Score</x-table.th>
|
|
||||||
<x-table.th>All Scores?</x-table.th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<x-table.body>
|
|
||||||
@foreach($entries as $entry)
|
|
||||||
<tr>
|
|
||||||
<x-table.td>{{ $entry->rank }}</x-table.td>
|
|
||||||
<x-table.td>{{ $entry->id }}</x-table.td>
|
|
||||||
<x-table.td>{{ $entry->draw_number }}</x-table.td>
|
|
||||||
<x-table.td>
|
|
||||||
<span>{{ $entry->student->full_name() }}, </span>
|
|
||||||
<span class="text-xs text-gray-400">{{ $entry->student->school->name }}</span>
|
|
||||||
</x-table.td>
|
|
||||||
<x-table.td class="!py-0">
|
|
||||||
@if($doublerService->studentIsDoubler($entry->student_id))
|
|
||||||
<x-doubler-block :doublerEntryInfo="$doublerService->getDoublerInfo($entry->student_id)" />
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{-- @if($entry->is_doubler)--}}
|
|
||||||
{{-- <x-doubler-block :studentID="$entry->student->id" />--}}
|
|
||||||
{{-- @endif--}}
|
|
||||||
</x-table.td>
|
|
||||||
<x-table.td>{{ number_format($entry->final_score_array[0] ?? 0,4) }}</x-table.td>
|
|
||||||
<x-table.td>@if($entry->scoring_complete) <x-icons.checkmark color="green" /> @endif</x-table.td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</x-table.body>
|
|
||||||
</x-table.table>
|
|
||||||
</x-card.card>
|
|
||||||
|
|
||||||
|
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
@props(['doublerEntryInfo'])
|
@php($doublerEntryInfo = $doublerService->getDoublerInfo($entry->student_id))
|
||||||
@php($doublerButtonClasses = 'hidden rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:block')
|
@php($doublerButtonClasses = 'hidden rounded-md bg-white px-2.5 py-1.5 text-xs text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:block')
|
||||||
<ul role="list" class="">
|
<ul role="list" class="">
|
||||||
|
|
||||||
@foreach($doublerEntryInfo as $info)
|
@foreach($doublerEntryInfo as $info)
|
||||||
@php($isopen = $info['status'] == 'undecided')
|
@php($isopen = $info['status'] == 'undecided')
|
||||||
<li class="pb-2 pt-0 px-0 my-2 rounded-xl border border-gray-200 " x-data="{ open: {{ $isopen ? 'true':'false' }} }">
|
<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" >
|
<div class="flex items-start gap-x-3 bg-gray-100 px-3 py-2" >
|
||||||
<p class="text-sm font-semibold leading-6 text-gray-900">
|
<p class="text-sm font-semibold leading-6 text-gray-900">
|
||||||
<a href="/tabulation/auditions/{{ $info['auditionID'] }}">
|
<a href="/tabulation/auditions/{{ $info['auditionID'] }}">
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2" x-show="open">
|
<div class="grid grid-cols-4" x-show="open">
|
||||||
<div class="mt-1 px-3 text-xs leading-5 text-gray-500">
|
<div class="mt-1 px-3 text-xs leading-5 text-gray-500 col-span-3">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="flex items-center gap-x-2">
|
<li class="flex items-center gap-x-2">
|
||||||
<p class="whitespace-nowrap">Ranked {{ $info['rank'] }}</p>
|
<p class="whitespace-nowrap">Ranked {{ $info['rank'] }}</p>
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-x-4">
|
<div class="flex flex-col justify-end gap-y-1 pt-1">
|
||||||
@if ($info['status'] === 'undecided')
|
@if ($info['status'] === 'undecided')
|
||||||
<form method="POST" action="{{ route('doubler.accept',['entry'=>$info['entryID']]) }}">
|
<form method="POST" action="{{ route('doubler.accept',['entry'=>$info['entryID']]) }}">
|
||||||
@csrf
|
@csrf
|
||||||
Loading…
Reference in New Issue