Tabellone, badge e brand sono ricodificati nel flusso _air via OverlayRelay; sync punteggio HTTP, volume condiviso rails/sidekiq, qualità 720p migliorata e badge CONNECTING in ripresa da pausa. Co-authored-by: Cursor <cursoragent@cursor.com>
112 lines
3.0 KiB
Ruby
112 lines
3.0 KiB
Ruby
module Scoring
|
|
class ApplyAction
|
|
Result = Struct.new(:score, :set_won, :match_won, :winner, keyword_init: true)
|
|
|
|
def initialize(session:, action:)
|
|
@session = session
|
|
@match = session.match
|
|
@action = action.to_s
|
|
@rules = Rules.from_match(@match)
|
|
end
|
|
|
|
def call
|
|
score = @session.score_state || @session.create_score_state!(
|
|
home_sets: 0, away_sets: 0, home_points: 0, away_points: 0, current_set: 1, set_partials: []
|
|
)
|
|
|
|
case @action
|
|
when "home_point"
|
|
apply_point(score, :home)
|
|
when "away_point"
|
|
apply_point(score, :away)
|
|
when "home_undo"
|
|
apply_undo(score, :home)
|
|
when "away_undo"
|
|
apply_undo(score, :away)
|
|
when "close_set"
|
|
apply_close_set(score)
|
|
else
|
|
raise ArgumentError, "Azione non valida"
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def apply_point(score, side)
|
|
if side == :home
|
|
score.home_points += 1
|
|
else
|
|
score.away_points += 1
|
|
end
|
|
score.save!
|
|
broadcast(score)
|
|
winner = @rules.set_winner_from_points(
|
|
home_points: score.home_points,
|
|
away_points: score.away_points,
|
|
current_set: score.current_set
|
|
)
|
|
Result.new(score: score, set_won: winner.present?, match_won: false, winner: winner)
|
|
end
|
|
|
|
def apply_undo(score, side)
|
|
if side == :home
|
|
score.home_points = [score.home_points - 1, 0].max
|
|
else
|
|
score.away_points = [score.away_points - 1, 0].max
|
|
end
|
|
score.save!
|
|
broadcast(score)
|
|
Result.new(score: score, set_won: false, match_won: false, winner: nil)
|
|
end
|
|
|
|
def apply_close_set(score)
|
|
winner = @rules.set_winner_from_points(
|
|
home_points: score.home_points,
|
|
away_points: score.away_points,
|
|
current_set: score.current_set
|
|
)
|
|
winner ||= score.home_points > score.away_points ? :home : :away if score.home_points != score.away_points
|
|
return Result.new(score: score, set_won: false, match_won: false, winner: nil) unless winner
|
|
|
|
close_set_for(score, winner)
|
|
end
|
|
|
|
def close_set_for(score, winner)
|
|
partials = Array(score.set_partials)
|
|
partials << {
|
|
"set" => score.current_set,
|
|
"home" => score.home_points,
|
|
"away" => score.away_points
|
|
}
|
|
|
|
if winner == :home
|
|
score.home_sets += 1
|
|
else
|
|
score.away_sets += 1
|
|
end
|
|
|
|
match_winner = @rules.match_winner(home_sets: score.home_sets, away_sets: score.away_sets)
|
|
|
|
score.assign_attributes(
|
|
set_partials: partials,
|
|
home_points: 0,
|
|
away_points: 0,
|
|
current_set: score.current_set + 1
|
|
)
|
|
score.save!
|
|
broadcast(score)
|
|
Result.new(
|
|
score: score,
|
|
set_won: true,
|
|
match_won: match_winner.present?,
|
|
winner: match_winner || winner
|
|
)
|
|
end
|
|
|
|
def broadcast(score)
|
|
SessionChannel.broadcast_message(@session, score.as_cable_payload)
|
|
Streams::Overlay::Refresh.call(@session)
|
|
end
|
|
end
|
|
end
|