Introduce architettura multi-sport con catalogo, engine scoring e overlay.
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>
This commit is contained in:
94
backend/app/domain/sports/catalog.rb
Normal file
94
backend/app/domain/sports/catalog.rb
Normal file
@@ -0,0 +1,94 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Sports
|
||||
class Catalog
|
||||
LEGACY_SPORT_MAP = {
|
||||
"volleyball" => "pallavolo"
|
||||
}.freeze
|
||||
|
||||
class << self
|
||||
def all
|
||||
@all ||= load_entries
|
||||
end
|
||||
|
||||
def keys
|
||||
all.keys
|
||||
end
|
||||
|
||||
def find(key)
|
||||
normalized = normalize_key(key)
|
||||
entry = all[normalized]
|
||||
raise KeyError, "Sport sconosciuto: #{key}" unless entry
|
||||
|
||||
entry.merge(key: normalized)
|
||||
end
|
||||
|
||||
def find_optional(key)
|
||||
normalized = normalize_key(key)
|
||||
entry = all[normalized]
|
||||
return nil unless entry
|
||||
|
||||
entry.merge(key: normalized)
|
||||
end
|
||||
|
||||
def board_for(key)
|
||||
find(key)[:board]
|
||||
end
|
||||
|
||||
def overlay_for(key)
|
||||
find(key)[:overlay]
|
||||
end
|
||||
|
||||
def allowed_overlays_for(key)
|
||||
find(key)[:allowed_overlays]
|
||||
end
|
||||
|
||||
def default_rules_for(key)
|
||||
deep_stringify_keys(find(key)[:default_rules] || {})
|
||||
end
|
||||
|
||||
def normalize_key(key)
|
||||
raw = key.to_s.strip
|
||||
return "pallavolo" if raw.blank?
|
||||
|
||||
LEGACY_SPORT_MAP.fetch(raw, raw)
|
||||
end
|
||||
|
||||
def as_api_list
|
||||
all.map do |key, entry|
|
||||
{
|
||||
key: key,
|
||||
label: entry[:label],
|
||||
board: entry[:board],
|
||||
overlay: entry[:overlay],
|
||||
allowed_overlays: entry[:allowed_overlays],
|
||||
default_rules: entry[:default_rules] || {}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_entries
|
||||
path = Rails.root.join("config/sports.yml")
|
||||
raw = YAML.safe_load(File.read(path), permitted_classes: [], aliases: true) || {}
|
||||
raw.transform_keys(&:to_s).transform_values do |entry|
|
||||
entry.deep_symbolize_keys
|
||||
end.freeze
|
||||
end
|
||||
|
||||
def deep_stringify_keys(value)
|
||||
case value
|
||||
when Hash
|
||||
value.each_with_object({}) do |(k, v), h|
|
||||
h[k.to_s] = deep_stringify_keys(v)
|
||||
end
|
||||
when Array
|
||||
value.map { |v| deep_stringify_keys(v) }
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user