module Public module TournamentsHelper def tournament_team_chip(participant, name: nil) label = name.presence || participant&.name.presence || t("tournaments.tbd") logo = participant&.effective_logo_url content_tag(:span, class: "tournament-team-chip") do parts = [] if logo.present? parts << image_tag(logo, alt: "", width: 28, height: 28) end parts << content_tag(:span, label) safe_join(parts) end end def tournament_datetime_local(time) time&.in_time_zone&.strftime("%Y-%m-%dT%H:%M") end def tournament_invite_default_html(tournament, invited_by) Tournaments::ComposeInviteEmail.default_html(tournament: tournament, invited_by: invited_by) end def tournament_invite_editor_html(tournament, invited_by) stored = tournament.invite_draft_html.to_s return tournament_invite_default_html(tournament, invited_by) if stored.blank? Tournaments::ComposeInviteEmail.sanitize_html(stored) end def tournament_streaming_operator_label(user) user&.name.presence || user&.email.presence || "—" end def tournament_pending_invites_for(match) Array(@pending_invites_by_match_id&.[](match.id)) end def tournament_invite_cancel_confirm(invitation) count = @matches.to_a.count { |match| invitation.covers_match?(match) } if count > 1 t("tournaments.hub.streaming_cancel_multi", email: invitation.email, count: count) else t("tournaments.hub.streaming_cancel", email: invitation.email) end end def tournament_matches_grouped_by_date(matches) matches.group_by { |match| match.scheduled_at&.in_time_zone&.to_date } end def tournament_streaming_coverage(matches) assigned = pending = open = 0 matches.each do |match| if match.broadcast_assignments.any? assigned += 1 elsif tournament_pending_invites_for(match).any? pending += 1 else open += 1 end end { assigned: assigned, pending: pending, open: open, total: matches.size } end def tournament_broadcast_live_state(match) sessions = match.stream_sessions.to_a latest = sessions.max_by(&:created_at) if latest && !latest.status.in?(%w[ended error]) return :live if latest.status.in?(%w[live reconnecting paused]) return :waiting_operator end return :ended if sessions.any? { |session| session.status.in?(%w[ended error]) } || match.played? if match.broadcast_assignments.any? return :waiting_time if match.scheduled_upcoming? return :waiting_operator end return :waiting_operator if tournament_pending_invites_for(match).any? :uncovered end def tournament_streaming_live_counts(matches) counts = Hash.new(0) matches.each { |match| counts[tournament_broadcast_live_state(match)] += 1 } counts end def tournament_public_live_session(match) @live_by_match_id&.[](match.id) end def tournament_public_recording(match) @recording_by_match_id&.[](match.id) end def tournament_public_board_state(match) return :live if tournament_public_live_session(match) return :replay if tournament_public_recording(match) return :ended if match.played? || match.result_status.to_s.start_with?("walkover") || match.home_score.present? return :scheduled if match.scheduled_upcoming? :waiting end def tournament_public_score_label(match) return "#{match.home_score}–#{match.away_score}" if match.home_score.present? && match.away_score.present? session = tournament_public_live_session(match) score = session&.score_state return unless score "#{score.home_points}–#{score.away_points}" end def tournament_match_sides_locked?(match) match.played? || match.result_status.to_s.start_with?("walkover") end def tournament_phase_label(match) match.tournament_round&.name.presence || match.tournament_group&.name.presence || "—" end def tournament_side_blank_label(match, side) source = tournament_side_source_label(match, side) source.presence || t("tournaments.tbd") end def tournament_side_source_label(match, side) kind = match.public_send("#{side}_source_kind").to_s case kind when "winner_match" source = tournament_source_match(match, side) return t("tournaments.hub.winner_tbd") if source.blank? t("tournaments.hub.winner_of", match: source.matchup_label) when "group_rank" group = tournament_source_group(match, side) rank = match.public_send("#{side}_source_rank").to_i return t("tournaments.hub.group_rank_tbd") if group.blank? || rank <= 0 t("tournaments.hub.group_rank", group: group.name, rank: rank) end end def tournament_source_match(match, side) id = match.public_send("#{side}_source_match_id") return if id.blank? @matches&.find { |item| item.id == id } || Match.find_by(id: id) end def tournament_source_group(match, side) id = match.public_send("#{side}_source_group_id") return if id.blank? @groups&.find { |item| item.id == id } || TournamentGroup.find_by(id: id) end end end