Progress on tab pages
This commit is contained in:
parent
1f4f919c48
commit
2d00473b2c
|
|
@ -12,7 +12,6 @@ use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||||
use function mb_substr;
|
use function mb_substr;
|
||||||
use function sendMessage;
|
|
||||||
|
|
||||||
class CreateNewUser implements CreatesNewUsers
|
class CreateNewUser implements CreatesNewUsers
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
use Throwable;
|
||||||
|
use App\Exceptions\TabulationException;
|
||||||
|
|
||||||
|
class Handler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
public function render($request, Throwable $e)
|
||||||
|
{
|
||||||
|
if ($e instanceof TabulationException) {
|
||||||
|
dd('here');
|
||||||
|
return redirect('/tabulation/status')->with('warning', $e->getMessage());
|
||||||
|
}
|
||||||
|
return parent::render($request, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Throwable;
|
||||||
|
use function dd;
|
||||||
|
use function redirect;
|
||||||
|
|
||||||
|
class TabulationException extends Exception
|
||||||
|
{
|
||||||
|
public function report(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render($request)
|
||||||
|
{
|
||||||
|
// if ($e instanceof TabulationException) {
|
||||||
|
return redirect('/tabulation/status')->with('error', $this->getMessage());
|
||||||
|
// }
|
||||||
|
// return parent::render($request, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ class EntryController extends Controller
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
if(! Auth::user()->is_admin) abort(403);
|
||||||
$filters = session('adminEntryFilters');
|
$filters = session('adminEntryFilters') ?? null;
|
||||||
$minGrade = Audition::min('minimum_grade');
|
$minGrade = Audition::min('minimum_grade');
|
||||||
$maxGrade = Audition::max('maximum_grade');
|
$maxGrade = Audition::max('maximum_grade');
|
||||||
$auditions = Audition::orderBy('score_order')->get();
|
$auditions = Audition::orderBy('score_order')->get();
|
||||||
|
|
@ -26,6 +26,10 @@ class EntryController extends Controller
|
||||||
$entries = Entry::with(['student.school','audition']);
|
$entries = Entry::with(['student.school','audition']);
|
||||||
$entries->orderBy('updated_at','DESC');
|
$entries->orderBy('updated_at','DESC');
|
||||||
if($filters) {
|
if($filters) {
|
||||||
|
if($filters['id']) {
|
||||||
|
$entries->where('id', $filters['id']);
|
||||||
|
}
|
||||||
|
|
||||||
if($filters['audition']) {
|
if($filters['audition']) {
|
||||||
$entries->where('audition_id', $filters['audition']);
|
$entries->where('audition_id', $filters['audition']);
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +95,9 @@ class EntryController extends Controller
|
||||||
if(! Auth::user()->is_admin) abort(403);
|
if(! Auth::user()->is_admin) abort(403);
|
||||||
$students = Student::with('school')->orderBy('last_name')->orderBy('first_name')->get();
|
$students = Student::with('school')->orderBy('last_name')->orderBy('first_name')->get();
|
||||||
$auditions = Audition::orderBy('score_order')->get();
|
$auditions = Audition::orderBy('score_order')->get();
|
||||||
return view('admin.entries.edit', ['entry' => $entry, 'students' => $students, 'auditions' => $auditions]);
|
$scores = $entry->scoreSheets()->get();
|
||||||
|
// return view('admin.entries.edit', ['entry' => $entry, 'students' => $students, 'auditions' => $auditions]);
|
||||||
|
return view('admin.entries.edit', compact('entry', 'students', 'auditions','scores'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Entry $entry)
|
public function update(Entry $entry)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ use function abort;
|
||||||
use function dd;
|
use function dd;
|
||||||
use function request;
|
use function request;
|
||||||
use function response;
|
use function response;
|
||||||
use function sendMessage;
|
|
||||||
|
|
||||||
class ScoringGuideController extends Controller
|
class ScoringGuideController extends Controller
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ use App\Models\School;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use function abort;
|
use function abort;
|
||||||
use function sendMessage;
|
|
||||||
|
|
||||||
class EntryController extends Controller
|
class EntryController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -43,7 +42,7 @@ class EntryController extends Controller
|
||||||
public function destroy(Request $request, Entry $entry)
|
public function destroy(Request $request, Entry $entry)
|
||||||
{
|
{
|
||||||
$entry->delete();
|
$entry->delete();
|
||||||
sendMessage('The ' . $entry->audition->name . 'entry for ' . $entry->student->full_name(). 'has been deleted.','success');
|
return redirect('/entries')->with('success','The ' . $entry->audition->name . 'entry for ' . $entry->student->full_name(). 'has been deleted.');
|
||||||
return redirect('/entries');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ class FilterController extends Controller
|
||||||
public function adminEntryFilter(Request $request)
|
public function adminEntryFilter(Request $request)
|
||||||
{
|
{
|
||||||
$filters = array();
|
$filters = array();
|
||||||
|
$filters['id'] = request('id_filter') ?? null;
|
||||||
$filters['audition'] = request('audition_filter') ? request('audition_filter') : null;
|
$filters['audition'] = request('audition_filter') ? request('audition_filter') : null;
|
||||||
$filters['school'] = request('school_filter') ? request('school_filter') : null;
|
$filters['school'] = request('school_filter') ? request('school_filter') : null;
|
||||||
$filters['grade'] = request('grade_filter') ? request('grade_filter') : null;
|
$filters['grade'] = request('grade_filter') ? request('grade_filter') : null;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use App\Models\Entry;
|
||||||
use App\Models\ScoreSheet;
|
use App\Models\ScoreSheet;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
use function compact;
|
||||||
use function dump;
|
use function dump;
|
||||||
use function redirect;
|
use function redirect;
|
||||||
|
|
||||||
|
|
@ -18,6 +19,11 @@ class TabulationController extends Controller
|
||||||
return view('tabulation.choose_entry');
|
return view('tabulation.choose_entry');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function destroyScore(ScoreSheet $score) {
|
||||||
|
$score->delete();
|
||||||
|
return redirect()->back()->with('success','Score Deleted');
|
||||||
|
}
|
||||||
|
|
||||||
public function entryScoreSheet(Request $request)
|
public function entryScoreSheet(Request $request)
|
||||||
{
|
{
|
||||||
$existing_sheets = [];
|
$existing_sheets = [];
|
||||||
|
|
@ -74,5 +80,22 @@ class TabulationController extends Controller
|
||||||
return redirect()->route('tabulation.chooseEntry')->with('success',count($preparedScoreSheets) . " Scores created");
|
return redirect()->route('tabulation.chooseEntry')->with('success',count($preparedScoreSheets) . " Scores created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function status()
|
||||||
|
{
|
||||||
|
$auditions = Audition::with('entries.scoreSheets')->with('room.judges')->orderBy('score_order')->get();
|
||||||
|
|
||||||
|
return view('tabulation.status',compact('auditions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auditionSeating(Audition $audition)
|
||||||
|
{
|
||||||
|
// $entries = $audition->entries()->with(['student','scoreSheets.audition.scoringGuide','audition.room.judges'])->get();
|
||||||
|
// $entries = $entries->sortByDesc(function ($entry) {
|
||||||
|
// return $entry->totalScore();
|
||||||
|
// });
|
||||||
|
$entries = $audition->rankedEntries()->load('student','scoreSheets.audition.scoringGuide.subscores');
|
||||||
|
$judges = $audition->judges();
|
||||||
|
return view('tabulation.auditionSeating',compact('audition','entries','judges'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
use phpDocumentor\Reflection\Types\Boolean;
|
||||||
use PhpParser\Node\Scalar\String_;
|
use PhpParser\Node\Scalar\String_;
|
||||||
use function now;
|
use function now;
|
||||||
|
|
||||||
|
|
@ -30,6 +32,7 @@ class Audition extends Model
|
||||||
return $this->hasMany(Entry::class);
|
return $this->hasMany(Entry::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function room(): BelongsTo
|
public function room(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Room::class);
|
return $this->belongsTo(Room::class);
|
||||||
|
|
@ -119,4 +122,49 @@ class Audition extends Model
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public function judges()
|
||||||
|
// {
|
||||||
|
// // Very inefficient, need a better way
|
||||||
|
// return User::join('room_user', 'users.id', '=', 'room_user.user_id')
|
||||||
|
// ->join('rooms', 'room_user.room_id', '=', 'rooms.id')
|
||||||
|
// ->join('auditions', 'rooms.id', '=', 'auditions.room_id')
|
||||||
|
// ->where('auditions.id', $this->id)
|
||||||
|
// ->select('users.*') // avoid getting other tables' columns
|
||||||
|
// ->get();
|
||||||
|
// }
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function judges()
|
||||||
|
{
|
||||||
|
return $this->room->judges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scoredEntries()
|
||||||
|
{
|
||||||
|
return $this->entries->filter(function($entry) {
|
||||||
|
return $entry->scoreSheets->count() >= $this->judges()->count();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rankedEntries()
|
||||||
|
{
|
||||||
|
$entries = $this->entries()->with(['audition.scoringGuide.subscores','scoreSheets.judge'])->get();
|
||||||
|
$entries = $entries->all();
|
||||||
|
usort($entries, function($a,$b) {
|
||||||
|
$aScores = $a->finalScoresArray();
|
||||||
|
$bScores = $b->finalScoresArray();
|
||||||
|
|
||||||
|
$length = min(count($aScores), count($bScores));
|
||||||
|
for ($i=0; $i<$length; $i++) {
|
||||||
|
if ($aScores[$i] !== $bScores[$i]) {
|
||||||
|
return $bScores[$i] - $aScores[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
$collection = new \Illuminate\Database\Eloquent\Collection($entries);
|
||||||
|
return $collection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Exceptions\TabulationException;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
@ -13,6 +14,7 @@ class Entry extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
protected $hasCheckedScoreSheets = false;
|
||||||
|
|
||||||
public function student(): BelongsTo
|
public function student(): BelongsTo
|
||||||
{
|
{
|
||||||
|
|
@ -38,10 +40,70 @@ class Entry extends Model
|
||||||
public function scoreSheets(): HasMany
|
public function scoreSheets(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(ScoreSheet::class);
|
return $this->hasMany(ScoreSheet::class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verifyScoreSheets()
|
||||||
|
{
|
||||||
|
if ($this->hasCheckedScoreSheets) return true;
|
||||||
|
$judges = $this->audition->room->judges;
|
||||||
|
foreach ($this->scoreSheets as $sheet) {
|
||||||
|
if (! $judges->contains($sheet->user_id)) {
|
||||||
|
$invalidJudge = User::find($sheet->user_id);
|
||||||
|
// redirect ('/tabulation')->with('warning','Invalid scores for entry ' . $this->id . ' exist from ' . $invalidJudge->full_name());
|
||||||
|
// Abort execution, and redirect to /tabulation with a warning message
|
||||||
|
throw new TabulationException('Invalid scores for entry ' . $this->id . ' exist from ' . $invalidJudge->full_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function scoreFromJudge($user): ScoreSheet|null
|
public function scoreFromJudge($user): ScoreSheet|null
|
||||||
{
|
{
|
||||||
return $this->scoreSheets()->where('user_id','=',$user)->first() ?? null;
|
// return $this->scoreSheets()->where('user_id','=',$user)->first() ?? null;
|
||||||
|
return $this->scoreSheets->firstWhere('user_id', $user) ?? null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function totalScore()
|
||||||
|
{
|
||||||
|
$this->verifyScoreSheets();
|
||||||
|
$totalScore = 0;
|
||||||
|
foreach ($this->scoreSheets as $sheet)
|
||||||
|
{
|
||||||
|
$totalScore += $sheet->totalScore();
|
||||||
|
}
|
||||||
|
return $totalScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws TabulationException
|
||||||
|
*/
|
||||||
|
public function finalScoresArray()
|
||||||
|
{
|
||||||
|
$this->verifyScoreSheets();
|
||||||
|
$finalScoresArray = [];
|
||||||
|
$subscoresTiebreakOrder = $this->audition->scoringGuide->subscores->sortBy('tiebreak_order');
|
||||||
|
// initialize the return array
|
||||||
|
foreach ($subscoresTiebreakOrder as $subscore) {
|
||||||
|
$finalScoresArray[$subscore->id] = 0;
|
||||||
|
}
|
||||||
|
// add the subscores from each score sheet
|
||||||
|
foreach($this->scoreSheets as $sheet) {
|
||||||
|
foreach($sheet->subscores as $ss) {
|
||||||
|
$finalScoresArray[$ss['subscore_id']] += $ss['score'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// calculate weighted final score
|
||||||
|
$totalScore = 0;
|
||||||
|
$totalWeight = 0;
|
||||||
|
foreach ($subscoresTiebreakOrder as $subscore) {
|
||||||
|
$totalScore += ($finalScoresArray[$subscore->id] * $subscore->weight);
|
||||||
|
$totalWeight += $subscore->weight;
|
||||||
|
}
|
||||||
|
$totalScore = ($totalScore / $totalWeight);
|
||||||
|
array_unshift($finalScoresArray,$totalScore);
|
||||||
|
return $finalScoresArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class RoomUser extends Model
|
||||||
|
{
|
||||||
|
public function user(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function judge(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function room(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Room::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
||||||
|
|
||||||
class ScoreSheet extends Model
|
class ScoreSheet extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +16,7 @@ class ScoreSheet extends Model
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = ['subscores' => 'json'];
|
protected $casts = ['subscores' => 'json'];
|
||||||
|
protected $with = ['entry','judge','audition.scoringGuide'];
|
||||||
|
|
||||||
public function entry(): BelongsTo
|
public function entry(): BelongsTo
|
||||||
{
|
{
|
||||||
|
|
@ -26,8 +28,37 @@ class ScoreSheet extends Model
|
||||||
return $this->belongsTo(User::class, 'user_id');
|
return $this->belongsTo(User::class, 'user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function audition(): HasOneThrough
|
||||||
|
{
|
||||||
|
return $this->hasOneThrough(
|
||||||
|
Audition::class, // The final model you want to access
|
||||||
|
Entry::class, // The intermediate model
|
||||||
|
'id', // Foreign key on the intermediate model (Entry)
|
||||||
|
'id', // Foreign key on the final model (Audition)
|
||||||
|
'entry_id', // Local key on the current model (ScoreSheet)
|
||||||
|
'audition_id' // Local key on the intermediate model (Entry)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function getSubscore($id)
|
public function getSubscore($id)
|
||||||
{
|
{
|
||||||
return $this->subscores[$id]['score'] ?? false;
|
return $this->subscores[$id]['score'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function totalScore() {
|
||||||
|
$totalScore = 0;
|
||||||
|
$totalWeights = 0;
|
||||||
|
foreach ( $this->audition->scoringGuide->subscores as $subscore) {
|
||||||
|
$totalScore += $this->getSubscore($subscore->id) * $subscore->weight;
|
||||||
|
$totalWeights += $subscore->weight;
|
||||||
|
}
|
||||||
|
return $totalScore / $totalWeights;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid() {
|
||||||
|
$judges = $this->audition->judges();
|
||||||
|
return $judges->contains('id', $this->judge->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class ScoringGuide extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
protected $with = ['subscores'];
|
||||||
|
|
||||||
public function auditions(): HasMany
|
public function auditions(): HasMany
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,12 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||||
return $this->first_name . ' ' . $this->last_name;
|
return $this->first_name . ' ' . $this->last_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function short_name(): String
|
||||||
|
{
|
||||||
|
// return the first letter of $this->first_name and the full $this->last_name
|
||||||
|
return $this->first_name[0] . '. ' . $this->last_name;
|
||||||
|
}
|
||||||
|
|
||||||
public function has_school(): bool
|
public function has_school(): bool
|
||||||
{
|
{
|
||||||
return $this->school_id !== null;
|
return $this->school_id !== null;
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,3 @@ function tw_max_width_class_array() :Array {
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMessages() {
|
|
||||||
$flash = Session::get('_flash');
|
|
||||||
$messages = $flash['new'];
|
|
||||||
$return = [];
|
|
||||||
foreach ($messages as $message) {
|
|
||||||
if (substr($message, 0,4) != 'msg|') continue;
|
|
||||||
$type = Session::get($message);
|
|
||||||
$return[] = ['message' => substr($message,4), 'type' => $type];
|
|
||||||
}
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendMessage(String $message, String $type = 'success') {
|
|
||||||
Session::flash('msg|'.$message,$type);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\ScoreSheet;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class ScoreAllAuditions extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$judges = User::all();
|
||||||
|
foreach ($judges as $judge) {
|
||||||
|
foreach( $judge->rooms as $room) {
|
||||||
|
foreach ($room->auditions as $audition){
|
||||||
|
$scoringGuide = $audition->scoringGuide;
|
||||||
|
$subscores = $scoringGuide->subscores;
|
||||||
|
foreach ($audition->entries as $entry){
|
||||||
|
$scoreArray = [];
|
||||||
|
foreach ($subscores as $subscore) {
|
||||||
|
$scoreArray[$subscore->id] = [
|
||||||
|
'score' => mt_rand(0,100),
|
||||||
|
'subscore_id' => $subscore->id,
|
||||||
|
'subscore_name' => $subscore->name
|
||||||
|
];
|
||||||
|
}
|
||||||
|
ScoreSheet::create([
|
||||||
|
'user_id' => $judge->id,
|
||||||
|
'entry_id' => $entry->id,
|
||||||
|
'subscores' => $scoreArray
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,32 @@
|
||||||
</x-form.footer>
|
</x-form.footer>
|
||||||
</x-form.form>
|
</x-form.form>
|
||||||
</x-card.card>
|
</x-card.card>
|
||||||
|
|
||||||
|
<x-card.card class="mx-auto max-w-2xl mt-6">
|
||||||
|
<x-card.heading>Scores</x-card.heading>
|
||||||
|
<x-card.list.body>
|
||||||
|
@foreach($scores as $score)
|
||||||
|
@php($score->isValid())
|
||||||
|
<x-card.list.row right_link_button_type="button" >
|
||||||
|
<div>{{ $score->judge->full_name() }}</div>
|
||||||
|
@foreach($score->subscores as $subscore)
|
||||||
|
{{-- TODO make this look better--}}
|
||||||
|
<div>
|
||||||
|
<p>{{$subscore['subscore_name']}}</p>
|
||||||
|
<p>{{$subscore['score'] }}</p>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
@if(! $score->isValid())
|
||||||
|
<form method="POST" action="/admin/scores/{{ $score->id }}">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<x-slot:right_link_button class="bg-red-500 text-white">INVALID SCORE - DELETE</x-slot:right_link_button>
|
||||||
|
@endif
|
||||||
|
</x-card.list.row>
|
||||||
|
{{-- // TODO make the invalid prettier--}}
|
||||||
|
@endforeach
|
||||||
|
</x-card.list.body>
|
||||||
|
</x-card.card>
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
||||||
{{--TODO apply javascript to only show appropriate auditions for the students grade--}}
|
{{--TODO apply javascript to only show appropriate auditions for the students grade--}}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
<x-card.heading>Set Filters</x-card.heading>
|
<x-card.heading>Set Filters</x-card.heading>
|
||||||
<x-form.form action="/filters/admin_entry_filter" method="POST">
|
<x-form.form action="/filters/admin_entry_filter" method="POST">
|
||||||
<x-form.body-grid columns="12">
|
<x-form.body-grid columns="12">
|
||||||
<x-form.select name="audition_filter" colspan="5">
|
<x-form.field name="id_filter" label_text="Entry ID" colspan="2" value="{{ $filters['id'] ?? '' }}"/>
|
||||||
|
<x-form.select name="audition_filter" colspan="4">
|
||||||
<x-slot:label>Audition</x-slot:label>
|
<x-slot:label>Audition</x-slot:label>
|
||||||
<option value="">No Audition Filter</option>
|
<option value="">No Audition Filter</option>
|
||||||
@foreach($auditions as $audition)
|
@foreach($auditions as $audition)
|
||||||
|
|
@ -15,7 +16,7 @@
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</x-form.select>
|
</x-form.select>
|
||||||
<x-form.select name="school_filter" colspan="5">
|
<x-form.select name="school_filter" colspan="4">
|
||||||
<x-slot:label>School</x-slot:label>
|
<x-slot:label>School</x-slot:label>
|
||||||
<option value="">No School Filter</option>
|
<option value="">No School Filter</option>
|
||||||
@foreach($schools as $school)
|
@foreach($schools as $school)
|
||||||
|
|
@ -39,7 +40,7 @@
|
||||||
<x-form.field name="last_name_filter" colspan="6" label_text="Last Name" value="{{ ($filters['last_name'] ?? null) }}"/>
|
<x-form.field name="last_name_filter" colspan="6" label_text="Last Name" value="{{ ($filters['last_name'] ?? null) }}"/>
|
||||||
</x-form.body-grid>
|
</x-form.body-grid>
|
||||||
<x-form.footer class="pb-4">
|
<x-form.footer class="pb-4">
|
||||||
<x-form.button-nocolor href="filters/admin_entry_filter/clear">Clear Filters</x-form.button-nocolor>
|
<x-form.button-nocolor href="/filters/admin_entry_filter/clear">Clear Filters</x-form.button-nocolor>
|
||||||
<x-form.button>Apply Filters</x-form.button>
|
<x-form.button>Apply Filters</x-form.button>
|
||||||
</x-form.footer>
|
</x-form.footer>
|
||||||
</x-form.form>
|
</x-form.form>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
@php
|
@php
|
||||||
$buttonClasses = "text-sm font-semibold leading-6 text-gray-900";
|
$buttonClasses = "text-sm font-semibold leading-6 text-gray-900";
|
||||||
@endphp
|
@endphp
|
||||||
|
@props(['href' => false])
|
||||||
<div>
|
<div>
|
||||||
|
@if($href)
|
||||||
|
<a href="{{ $href }}" {{ $attributes->merge(['class' => $buttonClasses]) }}>{{ $slot }}</a>
|
||||||
|
@else
|
||||||
<button {{ $attributes->merge(['class' => $buttonClasses, 'type'=>'submit']) }}>{{ $slot }}</button>
|
<button {{ $attributes->merge(['class' => $buttonClasses, 'type'=>'submit']) }}>{{ $slot }}</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
<div class="absolute left-1/2 z-10 mt-5 flex w-screen max-w-min -translate-x-1/2 px-4" x-show="open" x-cloak>
|
<div class="absolute left-1/2 z-10 mt-5 flex w-screen max-w-min -translate-x-1/2 px-4" x-show="open" x-cloak>
|
||||||
<div class="w-56 shrink rounded-xl bg-white p-4 text-sm font-semibold leading-6 text-gray-900 shadow-lg ring-1 ring-gray-900/5">
|
<div class="w-56 shrink rounded-xl bg-white p-4 text-sm font-semibold leading-6 text-gray-900 shadow-lg ring-1 ring-gray-900/5">
|
||||||
<a href="/tabulation/enter_scores" class="block p-2 hover:text-indigo-600">Enter Scores</a>
|
<a href="/tabulation/enter_scores" class="block p-2 hover:text-indigo-600">Enter Scores</a>
|
||||||
|
<a href="/tabulation/status" class="block p-2 hover:text-indigo-600">Audition Status</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<x-layout.app>
|
||||||
|
<x-slot:page_title>Audition Seating - {{ $audition->name }}</x-slot:page_title>
|
||||||
|
|
||||||
|
<x-table.table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th>ID</x-table.th>
|
||||||
|
<x-table.th>Draw #</x-table.th>
|
||||||
|
<x-table.th>Student Name</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>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<x-table.body>
|
||||||
|
@foreach($entries as $entry)
|
||||||
|
<tr>
|
||||||
|
<x-table.td>{{ $entry->id }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->draw_number }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->student->full_name(true) }}</x-table.td>
|
||||||
|
@foreach($judges as $judge)
|
||||||
|
<x-table.td>{{ number_format($entry->scoreFromJudge($judge->id)->totalScore(), 4) }}</x-table.td>
|
||||||
|
@endforeach
|
||||||
|
<x-table.td>{{ number_format($entry->totalScore(), 4) }}</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</x-table.table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<x-layout.app>
|
||||||
|
<x-slot:page_title>Audition Status</x-slot:page_title>
|
||||||
|
<x-card.card>
|
||||||
|
<x-card.heading>
|
||||||
|
Auditions
|
||||||
|
</x-card.heading>
|
||||||
|
<x-table.table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th>Audition</x-table.th>
|
||||||
|
<x-table.th>Scoring Status</x-table.th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<x-table.body>
|
||||||
|
@foreach($auditions as $audition)
|
||||||
|
<tr>
|
||||||
|
<x-table.td><a href="/tabulation/auditions/{{ $audition->id }}">
|
||||||
|
{{ $audition->name }}
|
||||||
|
</a></x-table.td>
|
||||||
|
<x-table.td>{{ $audition->scoredEntries()->count() }} / {{ $audition->entries->count() }} Scored</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</x-table.table>
|
||||||
|
</x-card.card>
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
@php use App\Models\Audition;
|
@php use App\Models\Audition;
|
||||||
use App\Models\Entry;use App\Models\School;
|
use App\Models\Entry;
|
||||||
|
use App\Models\School;
|
||||||
use App\Models\SchoolEmailDomain;
|
use App\Models\SchoolEmailDomain;
|
||||||
use App\Models\ScoreSheet;
|
use App\Models\ScoreSheet;
|
||||||
use App\Models\ScoringGuide;
|
use App\Models\ScoringGuide;
|
||||||
use App\Models\User;
|
use App\Models\User;use App\Settings;
|
||||||
use App\Settings;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
@ -13,19 +13,13 @@
|
||||||
<x-slot:page_title>Test Page</x-slot:page_title>
|
<x-slot:page_title>Test Page</x-slot:page_title>
|
||||||
|
|
||||||
@php
|
@php
|
||||||
dump(Auth::user()->scoreSheets->where('entry_id','=','997')->first()->subscores[6]['score']);
|
$audition = Audition::find(2);
|
||||||
echo "-----";
|
$ranked = $audition->rankedEntries();
|
||||||
dump(Auth::user()->scoresForEntry(997));
|
dump($ranked);
|
||||||
echo "-----";
|
echo "<hr>plain entries<hr>";
|
||||||
dump(Auth::user()->scoresForEntry(997)[6]['score']);
|
dump($audition->entries());
|
||||||
echo "-----";
|
|
||||||
dump(Auth::user()->scoresForEntry(997)[7]['score']);
|
|
||||||
echo "-----";
|
|
||||||
dump(Auth::user()->scoresForEntry(997)[8]['score']);
|
|
||||||
echo "-----";
|
|
||||||
dump(Auth::user()->scoresForEntry(997)[9]['score']);
|
|
||||||
echo "-----";
|
|
||||||
dump(Auth::user()->scoresForEntry(997)[10]['score']);
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ Route::middleware(['auth','verified',CheckIfCanTab::class])->prefix('tabulation/
|
||||||
Route::get('/record_noshow','chooseEntry');
|
Route::get('/record_noshow','chooseEntry');
|
||||||
Route::get('/entries','entryScoreSheet');
|
Route::get('/entries','entryScoreSheet');
|
||||||
Route::post('/entries/{entry}','saveEntryScoreSheet');
|
Route::post('/entries/{entry}','saveEntryScoreSheet');
|
||||||
|
Route::get('/status','status');
|
||||||
|
Route::get('/auditions/{audition}','auditionSeating');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -43,6 +45,7 @@ Route::middleware(['auth','verified',CheckIfCanTab::class])->prefix('tabulation/
|
||||||
// Admin Routes
|
// Admin Routes
|
||||||
Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->group(function() {
|
Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->group(function() {
|
||||||
Route::view('/','admin.dashboard');
|
Route::view('/','admin.dashboard');
|
||||||
|
Route::delete('/scores/{score}',[TabulationController::class,'destroyScore']);
|
||||||
Route::post('/auditions/roomUpdate',[\App\Http\Controllers\Admin\AuditionController::class,'roomUpdate']); // Endpoint for JS assigning auditions to rooms
|
Route::post('/auditions/roomUpdate',[\App\Http\Controllers\Admin\AuditionController::class,'roomUpdate']); // Endpoint for JS assigning auditions to rooms
|
||||||
Route::post('/scoring/assign_guide_to_audition',[\App\Http\Controllers\Admin\AuditionController::class,'scoringGuideUpdate']); // Endpoint for JS assigning scoring guides to auditions
|
Route::post('/scoring/assign_guide_to_audition',[\App\Http\Controllers\Admin\AuditionController::class,'scoringGuideUpdate']); // Endpoint for JS assigning scoring guides to auditions
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue