. Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. namespace App\Models; use App\Exceptions\InvariantException; use App\Models\Store\Product; use Carbon\Carbon; /** * @property \Carbon\Carbon|null $created_at * @property string $description * @property \Carbon\Carbon $end_date * @property string|null $header_banner * @property string|null $info_url * @property string $name * @property int $play_mode * @property \Illuminate\Database\Eloquent\Collection $profileBanners ProfileBanner * @property int|null $rank_max * @property int|null $rank_min * @property \Illuminate\Database\Eloquent\Collection $registrations TournamentRegistration * @property \Carbon\Carbon $signup_close * @property \Carbon\Carbon $signup_open * @property \Carbon\Carbon $start_date * @property int|null $tournament_banner_product_id * @property int $tournament_id * @property \Carbon\Carbon|null $updated_at */ class Tournament extends Model { protected $primaryKey = 'tournament_id'; protected $casts = [ 'end_date' => 'datetime', 'signup_close' => 'datetime', 'signup_open' => 'datetime', 'start_date' => 'datetime', ]; public static function getGroupedListing() { $tournaments = static::query() ->with('registrations') ->orderBy('tournament_id', 'desc') ->get(); $now = Carbon::now(); return [ 'current' => $tournaments->where('end_date', '>', $now), 'previous' => $tournaments->where('end_date', '<=', $now), ]; } public function profileBanners() { return $this->hasMany(ProfileBanner::class); } public function registrations() { return $this->hasMany(TournamentRegistration::class); } public function product() { return $this->belongsTo(Product::class, 'tournament_banner_product_id'); } public function isRegistrationOpen() { $now = Carbon::now(); return $this->signup_open < $now && $this->signup_close > $now; } public function isTournamentRunning() { $now = Carbon::now(); return $this->start_date < $now && $this->end_date > $now; } public function isStoreBannerAvailable() { return $this->tournament_banner_product_id !== null && $this->product->isAvailable(); } public function isSignedUp($user) { if (!$user) { return false; } return $this->registrations()->where('user_id', '=', $user->user_id)->exists(); } public function isValidRank($user) { if (!$user) { return false; } $userRank = UserStatistics\Model ::getClass($this->playModeStr(), $this->play_mode_variant) ::firstOrNew(['user_id' => $user->getKey()]) ->globalRank(); if ($this->rank_min !== null && ($userRank === null || $this->rank_min > $userRank)) { return false; } if ($this->rank_max !== null && ($userRank === null || $this->rank_max < $userRank)) { return false; } return true; } public function unregister($user) { //sanity check: we shouldn't be touching users once the tournament is already in action. if ($this->isTournamentRunning()) { throw new InvariantException('tournament is already running'); } $this->registrations()->where('user_id', '=', $user->user_id)->delete(); } public function register($user) { if ($this->isSignedUp($user)) { return; } //sanity check: we shouldn't be touching users once the tournament is already in action. if ($this->isTournamentRunning()) { throw new InvariantException('tournament is already running'); } $reg = new TournamentRegistration(); $reg->user()->associate($user); $this->registrations()->save($reg); } public function playModeStr() { return Beatmap::modeStr($this->play_mode); } public function pageLinks() { $links = []; if ($this->info_url !== null) { $links[] = [ 'url' => $this->info_url, 'title' => osu_trans('tournament.show.info_page'), ]; } if ($this->isStoreBannerAvailable()) { $links[] = [ 'url' => route('store.products.show', $this->tournament_banner_product_id), 'title' => osu_trans('tournament.show.banner'), ]; } return $links; } }