hasOne(EntryTotalScore::class); } /** * @throws AuditionAdminException */ public function rank(string $type) { $ranker = app(RankAuditionEntries::class); // 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; } return $rankedEntries->where('id', $this->id)->first()->advancementRank; /** The code below is deprecated and should be removed in the future. */ // TODO: Remove this code if nothing is breaking // // 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 canChangeDoublerDecision(): bool { // If results are published, we can't change our decision if ($this->audition->hasFlag('seats_published')) { return false; } $doubler = Doubler::findDoubler($this->student_id, $this->audition->event_id); // Return false if we're not a doubler if (is_null($doubler)) { return false; } // If we're only in two auditions and the other is published, we can't change our decision if (count($doubler->entries()) === 2) { foreach ($doubler->entries() as $entry) { if ($entry->audition->hasFlag('seats_published')) { return false; } } } // Deal with superDoublers if ($doubler->entries()->count() > 2) { // If the accepted entry is published, we can't change our decision if ($doubler->getAcceptedEntry()) { $testEntry = $doubler->getAcceptedEntry(); if ($testEntry->audition->hasFlag('seats_published')) { return false; } } // If all other entries are published, we can't change our decision foreach ($doubler->entries() as $entry) { if ($entry->id == $this->id) { continue; // We're not checking our own entry } if (! $entry->audition->hasFlag('seats_published')) { return true; // If there's at least one other unpublished entry, we can change our decision } } return false; // We didn't find any unpublised entries other than this one } return true; } 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 prelimScoreSheets(): HasMany { return $this->hasMany(PrelimScoreSheet::class); } public function prelimTotalScore() { return once(function () { $total = 0; foreach ($this->prelimScoreSheets as $sheet) { $total += $sheet->total; } return $total / $this->prelimScoreSheets->count(); }); } public function prelimResult() { if ($this->hasFlag('passed_prelim')) { return 'passed'; } if ($this->hasFlag('failed_prelim')) { return 'failed'; } return null; } 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, 'passed_prelim' => EntryFlags::PASSED_PRELIM, 'late_fee_waived' => EntryFlags::LATE_FEE_WAIVED, }; $this->flags()->create(['flag_name' => $enum]); $this->load('flags'); } public function removeFlag($flag): void { $thisFlag = EntryFlag::where('flag_name', $flag) ->where('entry_id', $this->id)->first(); $thisFlag?->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'); }); } }