module Scoring class Rules Side = Struct.new(:home, :away, keyword_init: true) def self.from_match(match) overrides = match.scoring_rules.is_a?(Hash) ? match.scoring_rules : {} new( sets_to_win: match.sets_to_win, points_per_set: overrides["points_per_set"] || overrides[:points_per_set] || 25, points_deciding_set: overrides["points_deciding_set"] || overrides[:points_deciding_set] || 15, min_point_lead: overrides["min_point_lead"] || overrides[:min_point_lead] || 2 ) 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 end end