*/ protected $fillable = [ 'name', 'slug', 'description', 'status', 'opening_date', 'closing_date', 'operating_season', 'size_acres', 'website', 'operator_id', 'total_areas', 'operating_areas', 'closed_areas', 'total_rides', 'total_coasters', 'total_flat_rides', 'total_water_rides', 'total_daily_capacity', 'average_wait_time', 'average_rating', 'total_rides_operated', 'total_rides_retired', 'last_expansion_date', 'last_major_update', 'utilization_rate', 'peak_daily_attendance', 'guest_satisfaction', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'status' => ParkStatus::class, 'opening_date' => 'date', 'closing_date' => 'date', 'size_acres' => 'decimal:2', 'total_areas' => 'integer', 'operating_areas' => 'integer', 'closed_areas' => 'integer', 'total_rides' => 'integer', 'total_coasters' => 'integer', 'total_flat_rides' => 'integer', 'total_water_rides' => 'integer', 'total_daily_capacity' => 'integer', 'average_wait_time' => 'integer', 'average_rating' => 'decimal:2', 'total_rides_operated' => 'integer', 'total_rides_retired' => 'integer', 'last_expansion_date' => 'date', 'last_major_update' => 'date', 'utilization_rate' => 'decimal:2', 'peak_daily_attendance' => 'integer', 'guest_satisfaction' => 'decimal:2', ]; /** * Get the operator that owns the park. */ public function operator(): BelongsTo { return $this->belongsTo(Operator::class); } /** * Get the areas in the park. */ public function areas(): HasMany { return $this->hasMany(ParkArea::class); } /** * Get formatted website URL (ensures proper URL format). */ public function getWebsiteUrlAttribute(): string { if (!$this->website) { return ''; } $website = $this->website; if (!str_starts_with($website, 'http://') && !str_starts_with($website, 'https://')) { $website = 'https://' . $website; } return $website; } /** * Get the status display classes for Tailwind CSS. */ public function getStatusClassesAttribute(): string { return $this->status->getStatusClasses(); } /** * Get a formatted display of the park's size. */ public function getSizeDisplayAttribute(): string { return $this->size_acres ? number_format($this->size_acres, 1) . ' acres' : 'Unknown size'; } /** * Get the formatted opening year. */ public function getOpeningYearAttribute(): ?string { return $this->opening_date?->format('Y'); } /** * Get a brief description suitable for cards and previews. */ public function getBriefDescriptionAttribute(): string { $description = $this->description ?? ''; return strlen($description) > 200 ? substr($description, 0, 200) . '...' : $description; } /** * Scope a query to only include operating parks. */ public function scopeOperating($query) { return $query->where('status', ParkStatus::OPERATING); } /** * Scope a query to only include closed parks. */ public function scopeClosed($query) { return $query->whereIn('status', [ ParkStatus::CLOSED_TEMP, ParkStatus::CLOSED_PERM, ParkStatus::DEMOLISHED, ]); } /** * Boot the model. */ protected static function boot() { parent::boot(); static::created(function (Park $park) { $park->operator?->updateStatistics(); }); static::deleted(function (Park $park) { $park->operator?->updateStatistics(); }); } }