Catalogo sport in YAML, board implicito, engine per volley/basket/timed/racket/timer/generic, regia e app Android allineate. Co-authored-by: Cursor <cursoragent@cursor.com>
75 lines
2.4 KiB
Ruby
75 lines
2.4 KiB
Ruby
module Scoring
|
|
class Rules
|
|
Side = Struct.new(:home, :away, keyword_init: true)
|
|
|
|
def self.from_match(match)
|
|
rules = match.effective_scoring_rules
|
|
board = match.effective_board_type
|
|
|
|
case board
|
|
when "volley", "racket"
|
|
new(
|
|
sets_to_win: rules["sets_to_win"].to_i,
|
|
points_per_set: rules["points_per_set"].to_i,
|
|
points_deciding_set: rules["points_deciding_set"].to_i,
|
|
min_point_lead: rules["min_point_lead"].to_i
|
|
)
|
|
when "basket", "timed"
|
|
PeriodRules.new(
|
|
periods: rules["periods"].to_i,
|
|
period_duration_secs: rules["period_duration_secs"].to_i,
|
|
overtime_duration_secs: rules["overtime_duration_secs"].to_i
|
|
)
|
|
else
|
|
new(
|
|
sets_to_win: rules["sets_to_win"].to_i.positive? ? rules["sets_to_win"].to_i : 3,
|
|
points_per_set: rules["points_per_set"].to_i.positive? ? rules["points_per_set"].to_i : 25,
|
|
points_deciding_set: rules["points_deciding_set"].to_i.positive? ? rules["points_deciding_set"].to_i : 15,
|
|
min_point_lead: rules["min_point_lead"].to_i.positive? ? rules["min_point_lead"].to_i : 2
|
|
)
|
|
end
|
|
end
|
|
|
|
def initialize(sets_to_win:, points_per_set: 25, points_deciding_set: 15, min_point_lead: 2)
|
|
@sets_to_win = sets_to_win
|
|
@points_per_set = points_per_set
|
|
@points_deciding_set = points_deciding_set
|
|
@min_point_lead = min_point_lead
|
|
end
|
|
|
|
def max_sets
|
|
(@sets_to_win * 2) - 1
|
|
end
|
|
|
|
def points_target(current_set)
|
|
current_set >= max_sets ? @points_deciding_set : @points_per_set
|
|
end
|
|
|
|
def set_winner_from_points(home_points:, away_points:, current_set:)
|
|
target = points_target(current_set)
|
|
if home_points >= target && (home_points - away_points) >= @min_point_lead
|
|
:home
|
|
elsif away_points >= target && (away_points - home_points) >= @min_point_lead
|
|
:away
|
|
end
|
|
end
|
|
|
|
def match_winner(home_sets:, away_sets:)
|
|
return :home if home_sets >= @sets_to_win
|
|
return :away if away_sets >= @sets_to_win
|
|
|
|
nil
|
|
end
|
|
|
|
class PeriodRules
|
|
attr_reader :periods, :period_duration_secs, :overtime_duration_secs
|
|
|
|
def initialize(periods:, period_duration_secs:, overtime_duration_secs: 300)
|
|
@periods = periods
|
|
@period_duration_secs = period_duration_secs
|
|
@overtime_duration_secs = overtime_duration_secs
|
|
end
|
|
end
|
|
end
|
|
end
|