startYear = config('siteData.etude_start_year'); $this->changeoverMonth = config('siteData.etude_changeover_month'); } /** * Get the audition year for a given date. * * The audition year follows a cycle based on the configured changeover month. * Before the changeover month, returns the current calendar year. * On or after the changeover month, returns the next calendar year. * * @param string|null $date Optional date string in 'YYYY-MM-DD' format. Defaults to the current date. * @return int The audition year * * @example * getCurrentAuditionYear('2024-01-15') // Returns 2024 (if changeover month is 3) * getCurrentAuditionYear('2024-03-01') // Returns 2025 (if changeover month is 3) * getCurrentAuditionYear() // Returns current audition year */ public function getCurrentAuditionYear(?string $date = null): int { $date = $date ? Carbon::parse($date) : now(); return $date->month < $this->changeoverMonth ? $date->year : $date->year + 1; } /** * Get the active school year as a string for a given date. * * @param string|null $date Optional date string in 'YYYY-MM-DD' format. Defaults to the current date. * @return string The school year in "YYYY - YYYY" format * * @example * getActiveSchoolYear('2024-01-15') // Returns "2023 - 2024" * getActiveSchoolYear('2024-09-01') // Returns "2024 - 2025" */ public function getActiveSchoolYear(?string $date = null): string { $auditionYear = $this->getCurrentAuditionYear($date); return ($auditionYear - 1).' - '.$auditionYear; } /** * Get the current set number for an ensemble in a given year. * * Sets rotate annually based on the ensemble's set count. * The rotation is calculated from the configured start year. * * @param Ensemble $ensemble The ensemble to get the set for * @param int|null $year Optional year. Defaults to current audition year. * @return int The set number (1 to ensemble's set_count) * * @example * getSetForEnsemble($ensemble, 2024) // Returns the set number for 2024 */ public function getSetForEnsemble(Ensemble $ensemble, ?int $year = null): int { $year = $year ?? $this->getCurrentAuditionYear(); $setCount = $ensemble->set_count; $yearDiff = $year - $this->startYear; return ($yearDiff % $setCount) + 1; } /** * Get the audition etude for a specific ensemble, instrument, and set combination. * * Results are cached in-memory for the duration of the request to avoid * duplicate queries when called multiple times with the same parameters. * * @param Ensemble $ensemble The ensemble to get the etude for * @param Instrument $instrument The instrument to get the etude for * @param int $set The set number * @return AuditionEtude|null The matching etude, or null if not found */ public function getEtude(Ensemble $ensemble, Instrument $instrument, int $set): ?AuditionEtude { $cacheKey = "{$ensemble->id}_{$instrument->id}_{$set}"; if (! isset($this->etudeCache[$cacheKey])) { $this->etudeCache[$cacheKey] = AuditionEtude::where('instrument_id', $instrument->id) ->where('ensemble_id', $ensemble->id) ->where('set', $set) ->first(); } return $this->etudeCache[$cacheKey]; } }