Billing Stripe, link regia mobile e staff solo trasmissione.

Aggiunge fatturazione club, pagina regia condivisibile senza account, roster squadre e rimuove la modalità controller dall'app (v1.1.0).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-29 07:23:13 +02:00
parent 4083bc5dee
commit f4b7be0f80
156 changed files with 5033 additions and 2033 deletions

View File

@@ -0,0 +1,110 @@
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)
end
end
end