Aggiunge i tornei con hub, pagina pubblica e tabellone per semifinali e finali.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
class Tournament < ApplicationRecord
|
||||
include Coverable
|
||||
|
||||
FORMAT_KINDS = %w[groups knockout mixed free].freeze
|
||||
STATUSES = %w[draft published live archived].freeze
|
||||
INTERNAL_TEAM_KIND = "tournament_broadcast"
|
||||
|
||||
belongs_to :club
|
||||
belongs_to :broadcast_team, class_name: "Team", optional: true
|
||||
has_many :broadcast_assignments, class_name: "TournamentBroadcastAssignment", dependent: :destroy
|
||||
has_many :matches, dependent: :destroy
|
||||
has_many :broadcast_invitations, class_name: "TournamentBroadcastInvitation", dependent: :destroy
|
||||
has_many :participants, class_name: "TournamentParticipant", dependent: :destroy
|
||||
has_many :rounds, class_name: "TournamentRound", dependent: :destroy
|
||||
has_many :groups, class_name: "TournamentGroup", dependent: :destroy
|
||||
has_many_attached :invite_email_images
|
||||
has_one_attached :logo_file
|
||||
|
||||
validates :name, presence: true
|
||||
validates :slug, presence: true, uniqueness: true,
|
||||
format: { with: /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/, message: "solo lettere minuscole, numeri e trattini" }
|
||||
validates :sport_key, presence: true
|
||||
validates :starts_on, :ends_on, presence: true
|
||||
validates :format_kind, inclusion: { in: FORMAT_KINDS }
|
||||
validates :status, inclusion: { in: STATUSES }
|
||||
validates :invite_draft_note, length: { maximum: 2000 }, allow_blank: true
|
||||
validate :sport_key_known
|
||||
validate :ends_on_not_before_starts_on
|
||||
validate :logo_file_type, if: -> { logo_file.attached? }
|
||||
|
||||
before_validation :normalize_sport_key
|
||||
before_validation :assign_slug, on: :create
|
||||
before_validation :normalize_slug, if: -> { slug_changed? && slug.present? }
|
||||
before_validation :normalize_courts
|
||||
|
||||
scope :visible_to_public, -> { where(status: %w[published live archived]) }
|
||||
scope :listed_on_live, -> { where(status: %w[published live]) }
|
||||
scope :search_public, lambda { |query|
|
||||
q = query.to_s.strip
|
||||
return all if q.blank?
|
||||
|
||||
term = "%#{sanitize_sql_like(q)}%"
|
||||
left_joins(:club).where(
|
||||
"tournaments.name ILIKE :term OR clubs.name ILIKE :term OR tournaments.venue ILIKE :term",
|
||||
term: term
|
||||
)
|
||||
}
|
||||
|
||||
def published?
|
||||
status.in?(%w[published live archived])
|
||||
end
|
||||
|
||||
def archived?
|
||||
status == "archived"
|
||||
end
|
||||
|
||||
def writable?
|
||||
!archived?
|
||||
end
|
||||
|
||||
def uses_groups?
|
||||
format_kind.in?(%w[groups mixed])
|
||||
end
|
||||
|
||||
def uses_knockout?
|
||||
format_kind.in?(%w[knockout mixed])
|
||||
end
|
||||
|
||||
def court_list
|
||||
Array(courts).map { |c| c.to_s.strip }.reject(&:blank?)
|
||||
end
|
||||
|
||||
def days
|
||||
(starts_on..ends_on).to_a
|
||||
end
|
||||
|
||||
def sport_label
|
||||
Sports::Catalog.find_optional(sport_key)&.dig(:label) || sport_key.to_s.humanize
|
||||
end
|
||||
|
||||
def public_page_path
|
||||
Rails.application.routes.url_helpers.public_tournament_page_path(slug)
|
||||
end
|
||||
|
||||
def effective_primary_color
|
||||
club.effective_primary_color
|
||||
end
|
||||
|
||||
def effective_secondary_color
|
||||
club.effective_secondary_color
|
||||
end
|
||||
|
||||
def effective_logo_url
|
||||
return unless logo_file.attached?
|
||||
|
||||
Rails.application.routes.url_helpers.rails_blob_path(logo_file, only_path: true)
|
||||
end
|
||||
|
||||
def concurrent_limit
|
||||
club.subscription&.plan&.concurrent_streams_limit
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def normalize_sport_key
|
||||
self.sport_key = Sports::Catalog.normalize_key(sport_key) if sport_key.present?
|
||||
end
|
||||
|
||||
def sport_key_known
|
||||
return if sport_key.blank?
|
||||
return if Sports::Catalog.find_optional(sport_key)
|
||||
|
||||
errors.add(:sport_key, "non valido")
|
||||
end
|
||||
|
||||
def ends_on_not_before_starts_on
|
||||
return if starts_on.blank? || ends_on.blank?
|
||||
return if ends_on >= starts_on
|
||||
|
||||
errors.add(:ends_on, "non può precedere la data di inizio")
|
||||
end
|
||||
|
||||
def assign_slug
|
||||
self.slug = Tournaments::GenerateSlug.call(self) if slug.blank?
|
||||
end
|
||||
|
||||
def normalize_slug
|
||||
self.slug = slug.to_s.parameterize
|
||||
end
|
||||
|
||||
def normalize_courts
|
||||
self.courts = court_list
|
||||
self.courts = ["Campo 1"] if courts.blank?
|
||||
end
|
||||
|
||||
def cover_parent
|
||||
club
|
||||
end
|
||||
|
||||
def logo_file_type
|
||||
return if logo_file.content_type.in?(Coverable::COVER_IMAGE_TYPES)
|
||||
|
||||
errors.add(:logo_file, I18n.t("coverable.errors.invalid_type"))
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user