hasOne(EntryTotalScore::class); } /** * @throws AuditionAdminException */ public function rank(string $type) { $ranker = app(RankAuditionEntries::class); if ($type !== 'seating' && $type !== 'advancement') { throw new AuditionAdminException('Invalid type specified. Must be either seating or advancement.'); } // Return false if no score. If we have no score, we can't have a rank if (! $this->totalScore) { return false; } // Get the ranked entries for this entries audition $rankedEntries = $ranker($this->audition, $type); // If we're looking for seating rank, return the rank from the list of ranked entries if ($type === 'seating') { return $rankedEntries->where('id', $this->id)->first()->seatingRank; } // Find position of current entry in the ranked entries (1-based index) $position = $rankedEntries->search(fn ($entry) => $entry->id === $this->id); // Return false if entry not found, otherwise return 1-based position return $position === false ? false : $position + 1; } public function student(): BelongsTo { return $this->belongsTo(Student::class); } public function audition(): BelongsTo { return $this->belongsTo(Audition::class); } public function school(): HasOneThrough { return $this->hasOneThrough( School::class, Student::class, 'id', 'id', 'student_id', 'school_id'); } public function scoreSheets(): HasMany { return $this->hasMany(ScoreSheet::class); } public function bonusScores(): HasMany { return $this->hasMany(BonusScore::class); } public function advancementVotes(): HasMany { return $this->hasMany(JudgeAdvancementVote::class); } public function flags(): HasMany { return $this->hasMany(EntryFlag::class); } public function hasFlag($flag): bool { $flags = []; foreach ($this->flags as $checkFlag) { $flags[] = $checkFlag->flag_name->value; } return in_array($flag, $flags); } public function addFlag($flag): void { if ($this->hasFlag($flag)) { return; } $enum = match ($flag) { 'will_advance' => EntryFlags::WILL_ADVANCE, 'declined' => EntryFlags::DECLINED, 'no_show' => EntryFlags::NO_SHOW, 'failed_prelim' => EntryFlags::FAILED_PRELIM, 'late_fee_waived' => EntryFlags::LATE_FEE_WAIVED, }; $this->flags()->create(['flag_name' => $enum]); $this->load('flags'); } public function removeFlag($flag): void { // remove the related auditionFlag where flag_name = $flag $this->flags()->where('flag_name', $flag)->delete(); $this->load('flags'); } /** * Ensures score_sheets_count property is always available */ public function getScoreSheetsCountAttribute() { if (! isset($this->attributes['score_sheets_count'])) { $this->attributes['score_sheets_count'] = $this->scoreSheets()->count(); } return $this->attributes['score_sheets_count']; } public function seat(): HasOne { return $this->hasOne(Seat::class); } public function scopeForSeating(Builder $query): void { $query->where('for_seating', 1); } public function scopeForAdvancement(Builder $query): void { $query->where('for_advancement', 1); } public function scopeAvailable(Builder $query): void { $query->whereDoesntHave('flags', function (Builder $query) { $query->where('flag_name', 'declined') ->orWhere('flag_name', 'no_show') ->orWhere('flag_name', 'failed_prelim'); }); } }