From edd792cce0eb77300f73a4184d87d784ef1ee387 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Fri, 14 Jun 2024 00:55:05 -0500 Subject: [PATCH] Get teh right entry data out to seating page --- .../Tabulation/TabulationController.php | 8 +- app/Models/ScoreSheet.php | 1 - app/Services/AuditionCacheService.php | 6 +- app/Services/TabulationService.php | 72 ++++ config/debugbar.php | 325 ++++++++++++++++++ .../tabulation/auditionSeating.blade.php | 23 +- 6 files changed, 409 insertions(+), 26 deletions(-) create mode 100644 config/debugbar.php diff --git a/app/Http/Controllers/Tabulation/TabulationController.php b/app/Http/Controllers/Tabulation/TabulationController.php index 231f7b1..124432b 100644 --- a/app/Http/Controllers/Tabulation/TabulationController.php +++ b/app/Http/Controllers/Tabulation/TabulationController.php @@ -37,9 +37,11 @@ class TabulationController extends Controller // $entries = $entries->sortByDesc(function ($entry) { // return $entry->totalScore(); // }); - $entries = $audition->rankedEntries()->load('student.entries.audition','scoreSheets.audition.scoringGuide.subscores'); - $judges = $audition->judges(); - return view('tabulation.auditionSeating',compact('audition','entries','judges')); +// $entries = $audition->rankedEntries()->load('student.entries.audition','scoreSheets.audition.scoringGuide.subscores'); + $entries = $this->tabulationService->auditionEntries($audition->id); + + + return view('tabulation.auditionSeating',compact('audition','entries')); } } diff --git a/app/Models/ScoreSheet.php b/app/Models/ScoreSheet.php index eb1ee73..8ede43b 100644 --- a/app/Models/ScoreSheet.php +++ b/app/Models/ScoreSheet.php @@ -16,7 +16,6 @@ class ScoreSheet extends Model ]; protected $casts = ['subscores' => 'json']; - protected $with = ['entry','judge','audition.scoringGuide']; public function entry(): BelongsTo { diff --git a/app/Services/AuditionCacheService.php b/app/Services/AuditionCacheService.php index 5f3d745..b8e4bf0 100644 --- a/app/Services/AuditionCacheService.php +++ b/app/Services/AuditionCacheService.php @@ -18,16 +18,16 @@ class AuditionCacheService } public function getAuditions(): \Illuminate\Database\Eloquent\Collection - { + { //TODO have changes to judging assignments refresh the cache return Cache::rememberForever($this->cacheKey, function () { - return Audition::with(['scoringGuide.subscores']) + return Audition::with(['scoringGuide.subscores','judges']) ->orderBy('score_order') ->get() ->keyBy('id'); }); } - public function getAudition($id) + public function getAudition($id): Audition { return $this->getAuditions()->firstWhere('id',$id); } diff --git a/app/Services/TabulationService.php b/app/Services/TabulationService.php index 2dbca7a..58d5f06 100644 --- a/app/Services/TabulationService.php +++ b/app/Services/TabulationService.php @@ -2,12 +2,15 @@ namespace App\Services; +use App\Exceptions\TabulationException; use App\Models\Audition; use App\Models\Entry; use App\Models\ScoreSheet; +use App\Models\User; use Illuminate\Support\Facades\Cache; use App\Services\AuditionCacheService; use Illuminate\Support\Facades\DB; +use function array_unshift; class TabulationService @@ -30,6 +33,75 @@ class TabulationService }); } + public function auditionEntries(Int $auditionId) + { + $cache_key = 'audition'.$auditionId.'entries'; + $audition = $this->auditionCacheService->getAudition($auditionId); + + return Cache::remember($cache_key, 2, function () use ($audition) { + $entries = Entry::where('audition_id',$audition->id)->with(['student.school','scoreSheets'])->get(); + + foreach ($entries as $entry) { + $entry->final_score_array = $this->entryFinalScores($entry); + } + + for ($n=0; $n <= $audition->judges_count; $n++) { + $entries = $entries->sortByDesc(function ($entry) use ($n) { + return $entry['final_score_array'][$n]; + }); + } + //TODO verify this actually sorts by subscores correcty + + return $entries; + }); + } + + /** + * @throws TabulationException + */ + public function entryFinalScores(Entry $entry) { + $audition = $this->auditionCacheService->getAudition($entry->audition_id); + $this->validateEntryScoreSheets($entry); + + $subscores = $audition->scoringGuide->subscores->sortBy('tiebreak_order'); + $finalScoresArray = []; + foreach($subscores as $subscore) { + $finalScoresArray[$subscore->id] = 0; + + } + + foreach ($entry->scoreSheets as $sheet) { + foreach ($sheet->subscores as $ss) { + $finalScoresArray[$ss['subscore_id']] += $ss['score']; + } + } + + // calculate weighted final score + $totalScore = 0; + $totalWeight = 0; + foreach ($subscores as $subscore) { + $totalScore += ($finalScoresArray[$subscore->id] * $subscore->weight); + $totalWeight += $subscore->weight; + } + $totalScore = ($totalScore / $totalWeight); + array_unshift($finalScoresArray,$totalScore); + return $finalScoresArray; + } + + /** + * @throws TabulationException + */ + public function validateEntryScoreSheets(Entry $entry): bool { + $audition = $this->auditionCacheService->getAudition($entry->audition_id); + foreach ($entry->scoreSheets as $sheet) { + if (! $audition->judges->contains($sheet->user_id)) { + $invalidJudge = User::find($sheet->user_id); + throw new TabulationException('Invalid scores for entry ' . $entry->id . ' exist from ' . $invalidJudge->full_name()); + } + } + return true; + } + public function getAuditionsWithStatus() { // Create an array with the number of scores for each entry diff --git a/config/debugbar.php b/config/debugbar.php new file mode 100644 index 0000000..44aff57 --- /dev/null +++ b/config/debugbar.php @@ -0,0 +1,325 @@ + env('DEBUGBAR_ENABLED', null), + 'except' => [ + 'telescope*', + 'horizon*', + ], + + /* + |-------------------------------------------------------------------------- + | Storage settings + |-------------------------------------------------------------------------- + | + | DebugBar stores data for session/ajax requests. + | You can disable this, so the debugbar stores data in headers/session, + | but this can cause problems with large data collectors. + | By default, file storage (in the storage folder) is used. Redis and PDO + | can also be used. For PDO, run the package migrations first. + | + | Warning: Enabling storage.open will allow everyone to access previous + | request, do not enable open storage in publicly available environments! + | Specify a callback if you want to limit based on IP or authentication. + | Leaving it to null will allow localhost only. + */ + 'storage' => [ + 'enabled' => true, + 'open' => env('DEBUGBAR_OPEN_STORAGE'), // bool/callback. + 'driver' => 'file', // redis, file, pdo, socket, custom + 'path' => storage_path('debugbar'), // For file driver + 'connection' => null, // Leave null for default connection (Redis/PDO) + 'provider' => '', // Instance of StorageInterface for custom driver + 'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver + 'port' => 2304, // Port to use with the "socket" driver + ], + + /* + |-------------------------------------------------------------------------- + | Editor + |-------------------------------------------------------------------------- + | + | Choose your preferred editor to use when clicking file name. + | + | Supported: "phpstorm", "vscode", "vscode-insiders", "vscode-remote", + | "vscode-insiders-remote", "vscodium", "textmate", "emacs", + | "sublime", "atom", "nova", "macvim", "idea", "netbeans", + | "xdebug", "espresso" + | + */ + + 'editor' => env('DEBUGBAR_EDITOR') ?: env('IGNITION_EDITOR', 'phpstorm'), + + /* + |-------------------------------------------------------------------------- + | Remote Path Mapping + |-------------------------------------------------------------------------- + | + | If you are using a remote dev server, like Laravel Homestead, Docker, or + | even a remote VPS, it will be necessary to specify your path mapping. + | + | Leaving one, or both of these, empty or null will not trigger the remote + | URL changes and Debugbar will treat your editor links as local files. + | + | "remote_sites_path" is an absolute base path for your sites or projects + | in Homestead, Vagrant, Docker, or another remote development server. + | + | Example value: "/home/vagrant/Code" + | + | "local_sites_path" is an absolute base path for your sites or projects + | on your local computer where your IDE or code editor is running on. + | + | Example values: "/Users//Code", "C:\Users\\Documents\Code" + | + */ + + 'remote_sites_path' => env('DEBUGBAR_REMOTE_SITES_PATH'), + 'local_sites_path' => env('DEBUGBAR_LOCAL_SITES_PATH', env('IGNITION_LOCAL_SITES_PATH')), + + /* + |-------------------------------------------------------------------------- + | Vendors + |-------------------------------------------------------------------------- + | + | Vendor files are included by default, but can be set to false. + | This can also be set to 'js' or 'css', to only include javascript or css vendor files. + | Vendor files are for css: font-awesome (including fonts) and highlight.js (css files) + | and for js: jquery and highlight.js + | So if you want syntax highlighting, set it to true. + | jQuery is set to not conflict with existing jQuery scripts. + | + */ + + 'include_vendors' => true, + + /* + |-------------------------------------------------------------------------- + | Capture Ajax Requests + |-------------------------------------------------------------------------- + | + | The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors), + | you can use this option to disable sending the data through the headers. + | + | Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools. + | + | Note for your request to be identified as ajax requests they must either send the header + | X-Requested-With with the value XMLHttpRequest (most JS libraries send this), or have application/json as a Accept header. + | + | By default `ajax_handler_auto_show` is set to true allowing ajax requests to be shown automatically in the Debugbar. + | Changing `ajax_handler_auto_show` to false will prevent the Debugbar from reloading. + */ + + 'capture_ajax' => true, + 'add_ajax_timing' => false, + 'ajax_handler_auto_show' => true, + 'ajax_handler_enable_tab' => true, + + /* + |-------------------------------------------------------------------------- + | Custom Error Handler for Deprecated warnings + |-------------------------------------------------------------------------- + | + | When enabled, the Debugbar shows deprecated warnings for Symfony components + | in the Messages tab. + | + */ + 'error_handler' => false, + + /* + |-------------------------------------------------------------------------- + | Clockwork integration + |-------------------------------------------------------------------------- + | + | The Debugbar can emulate the Clockwork headers, so you can use the Chrome + | Extension, without the server-side code. It uses Debugbar collectors instead. + | + */ + 'clockwork' => false, + + /* + |-------------------------------------------------------------------------- + | DataCollectors + |-------------------------------------------------------------------------- + | + | Enable/disable DataCollectors + | + */ + + 'collectors' => [ + 'phpinfo' => true, // Php version + 'messages' => true, // Messages + 'time' => true, // Time Datalogger + 'memory' => true, // Memory usage + 'exceptions' => true, // Exception displayer + 'log' => true, // Logs from Monolog (merged in messages if enabled) + 'db' => true, // Show database (PDO) queries and bindings + 'views' => true, // Views with their data + 'route' => true, // Current route information + 'auth' => false, // Display Laravel authentication status + 'gate' => true, // Display Laravel Gate checks + 'session' => true, // Display session data + 'symfony_request' => true, // Only one can be enabled.. + 'mail' => true, // Catch mail messages + 'laravel' => false, // Laravel version and environment + 'events' => false, // All events fired + 'default_request' => false, // Regular or special Symfony request logger + 'logs' => false, // Add the latest log messages + 'files' => false, // Show the included files + 'config' => false, // Display config settings + 'cache' => false, // Display cache events + 'models' => true, // Display models + 'livewire' => true, // Display Livewire (when available) + 'jobs' => false, // Display dispatched jobs + ], + + /* + |-------------------------------------------------------------------------- + | Extra options + |-------------------------------------------------------------------------- + | + | Configure some DataCollectors + | + */ + + 'options' => [ + 'time' => [ + 'memory_usage' => false, // Calculated by subtracting memory start and end, it may be inaccurate + ], + 'messages' => [ + 'trace' => true, // Trace the origin of the debug message + ], + 'memory' => [ + 'reset_peak' => false, // run memory_reset_peak_usage before collecting + 'with_baseline' => false, // Set boot memory usage as memory peak baseline + 'precision' => 0, // Memory rounding precision + ], + 'auth' => [ + 'show_name' => true, // Also show the users name/email in the debugbar + 'show_guards' => true, // Show the guards that are used + ], + 'db' => [ + 'with_params' => true, // Render SQL with the parameters substituted + 'backtrace' => true, // Use a backtrace to find the origin of the query in your files. + 'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults) + 'timeline' => false, // Add the queries to the timeline + 'duration_background' => true, // Show shaded background on each query relative to how long it took to execute. + 'explain' => [ // Show EXPLAIN output on queries + 'enabled' => false, + 'types' => ['SELECT'], // Deprecated setting, is always only SELECT + ], + 'hints' => false, // Show hints for common mistakes + 'show_copy' => false, // Show copy button next to the query, + 'slow_threshold' => false, // Only track queries that last longer than this time in ms + 'memory_usage' => false, // Show queries memory usage + 'soft_limit' => 100, // After the soft limit, no parameters/backtrace are captured + 'hard_limit' => 500, // After the hard limit, queries are ignored + ], + 'mail' => [ + 'timeline' => false, // Add mails to the timeline + 'show_body' => true, + ], + 'views' => [ + 'timeline' => false, // Add the views to the timeline (Experimental) + 'data' => false, //true for all data, 'keys' for only names, false for no parameters. + 'group' => 50, // Group duplicate views. Pass value to auto-group, or true/false to force + 'exclude_paths' => [ // Add the paths which you don't want to appear in the views + 'vendor/filament' // Exclude Filament components by default + ], + ], + 'route' => [ + 'label' => true, // show complete route on bar + ], + 'session' => [ + 'hiddens' => [], // hides sensitive values using array paths + ], + 'symfony_request' => [ + 'hiddens' => [], // hides sensitive values using array paths, example: request_request.password + ], + 'events' => [ + 'data' => false, // collect events data, listeners + ], + 'logs' => [ + 'file' => null, + ], + 'cache' => [ + 'values' => true, // collect cache values + ], + ], + + /* + |-------------------------------------------------------------------------- + | Inject Debugbar in Response + |-------------------------------------------------------------------------- + | + | Usually, the debugbar is added just before , by listening to the + | Response after the App is done. If you disable this, you have to add them + | in your template yourself. See http://phpdebugbar.com/docs/rendering.html + | + */ + + 'inject' => true, + + /* + |-------------------------------------------------------------------------- + | DebugBar route prefix + |-------------------------------------------------------------------------- + | + | Sometimes you want to set route prefix to be used by DebugBar to load + | its resources from. Usually the need comes from misconfigured web server or + | from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97 + | + */ + 'route_prefix' => '_debugbar', + + /* + |-------------------------------------------------------------------------- + | DebugBar route middleware + |-------------------------------------------------------------------------- + | + | Additional middleware to run on the Debugbar routes + */ + 'route_middleware' => [], + + /* + |-------------------------------------------------------------------------- + | DebugBar route domain + |-------------------------------------------------------------------------- + | + | By default DebugBar route served from the same domain that request served. + | To override default domain, specify it as a non-empty value. + */ + 'route_domain' => null, + + /* + |-------------------------------------------------------------------------- + | DebugBar theme + |-------------------------------------------------------------------------- + | + | Switches between light and dark theme. If set to auto it will respect system preferences + | Possible values: auto, light, dark + */ + 'theme' => env('DEBUGBAR_THEME', 'auto'), + + /* + |-------------------------------------------------------------------------- + | Backtrace stack limit + |-------------------------------------------------------------------------- + | + | By default, the DebugBar limits the number of frames returned by the 'debug_backtrace()' function. + | If you need larger stacktraces, you can increase this number. Setting it to 0 will result in no limit. + */ + 'debug_backtrace_limit' => 50, +]; diff --git a/resources/views/tabulation/auditionSeating.blade.php b/resources/views/tabulation/auditionSeating.blade.php index 51abf3d..ef8d256 100644 --- a/resources/views/tabulation/auditionSeating.blade.php +++ b/resources/views/tabulation/auditionSeating.blade.php @@ -21,27 +21,12 @@ {{ $entry->id }} {{ $entry->draw_number }} - {{ $entry->student->full_name(true) }} - @if($entry->student->isDoubler()) - - @endif - -{{-- @foreach($judges as $judge)--}} -{{-- --}} -{{-- @php--}} -{{-- $thisJudgeScore = $entry->scoreFromJudge($judge->id)?->totalScore();--}} -{{-- @endphp--}} -{{-- {{ $thisJudgeScore ? number_format($thisJudgeScore,4) : '' }}--}} -{{-- --}} -{{-- @endforeach--}} - {{ number_format($entry->totalScore(), 4) }} - - @if($entry->fullyJudged()) - - @endif - + {{ $entry->student->full_name() }}, + {{ $entry->student->school->name }} + Doubler Block + {{ $entry->final_score_array[0] }} @endforeach