lib/head_music/clef.rb in head_music-0.24.0 vs lib/head_music/clef.rb in head_music-0.24.1
- old
+ new
@@ -1,95 +1,25 @@
# frozen_string_literal: true
+require 'yaml'
+
# A clef assigns pitches to the lines and spaces of a staff.
class HeadMusic::Clef
include HeadMusic::Named
- CLEFS = [
- {
- pitch: 'G4', line: 2,
- names: %w[treble G-clef],
- modern: true,
- unicode: '𝄞', html_entity: '𝄞',
- },
- {
- pitch: 'G4', line: 1,
- names: ['French', 'French violin'],
- unicode: '𝄞', html_entity: '𝄞',
- },
- {
- pitch: 'G3', line: 2,
- names: ['choral tenor', 'tenor', 'tenor G-clef'],
- modern: true,
- unicode: '𝄠', html_entity: '𝄠',
- },
- {
- pitch: 'F3', line: 3,
- names: ['baritone'],
- unicode: '𝄢', html_entity: '𝄢',
- },
- {
- pitch: 'F3', line: 4,
- names: %w[bass F-clef],
- modern: true,
- unicode: '𝄢', html_entity: '𝄢',
- },
- {
- pitch: 'F3', line: 5,
- names: ['sub-bass'],
- unicode: '𝄢', html_entity: '𝄢',
- },
- {
- pitch: 'C4', line: 1,
- names: ['soprano'],
- unicode: '𝄡', html_entity: '𝄡',
- },
- {
- pitch: 'C4', line: 2,
- names: ['mezzo-soprano'],
- unicode: '𝄡', html_entity: '𝄡',
- },
- {
- pitch: 'C4', line: 3,
- names: %w[alto viola counter-tenor countertenor C-clef],
- modern: true,
- unicode: '𝄡', html_entity: '𝄡',
- },
- {
- pitch: 'C4', line: 4,
- names: ['tenor', 'tenor C-clef'],
- modern: true,
- unicode: '𝄡', html_entity: '𝄡',
- },
- {
- pitch: 'C4', line: 5,
- names: ['baritone', 'baritone C-clef'],
- unicode: '𝄡', html_entity: '𝄡',
- },
- {
- pitch: nil, line: 3,
- names: %w[neutral percussion],
- modern: true,
- unicode: '𝄥', html_entity: '𝄥',
- },
- ].freeze
+ RECORDS = YAML.load_file(File.expand_path('data/clefs.yml', __dir__)).freeze
def self.get(name)
get_by_name(name)
end
- attr_reader :pitch, :line, :musical_symbol
+ attr_reader :pitch, :line, :musical_symbols
delegate :ascii, :html_entity, :unicode, to: :musical_symbol
- def initialize(name)
- @name = name.to_s
- clef_data = CLEFS.detect { |clef| clef[:names].map(&:downcase).include?(name.downcase) }
- @pitch = HeadMusic::Pitch.get(clef_data[:pitch])
- @line = clef_data[:line]
- @modern = clef_data[:modern]
- @musical_symbol = HeadMusic::MusicalSymbol.new(clef_data.slice(:ascii, :html_entity, :unicode))
+ def musical_symbol
+ musical_symbols.first
end
def clef_type
"#{pitch.letter_name}-clef"
end
@@ -113,8 +43,61 @@
def modern?
@modern
end
def ==(other)
- to_s == other.to_s
+ HeadMusic::Utilities::HashKey.for(self) == HeadMusic::Utilities::HashKey.for(other)
+ end
+
+ def name(locale_code: Locale::DEFAULT_CODE)
+ I18n.translate(name_key, scope: :clefs, locale: locale_code)
+ end
+
+ private_class_method :new
+
+ private
+
+ def initialize(name)
+ record = record_for_name(name)
+ initialize_data_from_record(record)
+ end
+
+ def record_for_name(name)
+ name = name.to_s.strip
+ key = HeadMusic::Utilities::HashKey.for(name)
+ RECORDS.detect do |record|
+ name_keys = name_keys_from_record(record)
+ name_keys.include?(key) || name_key_translations(name_keys).include?(name)
+ end
+ end
+
+ def name_keys_from_record(record)
+ ([record[:name_key]] + [record[:alias_name_keys]]).flatten.compact.uniq.map(&:to_sym)
+ end
+
+ def name_key_translations(name_keys)
+ name_keys.map do |name_key|
+ I18n.config.available_locales.map do |locale_code|
+ I18n.translate(name_key, scope: :clefs, locale: locale_code)
+ end.flatten.uniq.compact
+ end.flatten.uniq.compact
+ end
+
+ def initialize_data_from_record(record)
+ initialize_keys_from_record(record)
+ @pitch = HeadMusic::Pitch.get(record[:pitch])
+ @line = record[:line]
+ @modern = record[:modern]
+ initialize_musical_symbols(record[:symbols])
+ end
+
+ def initialize_keys_from_record(record)
+ @name_key = record[:name_key]
+ @alias_name_keys = [record[:alias_name_keys]].flatten.compact
+ end
+
+ def initialize_musical_symbols(list)
+ @musical_symbols = (list || []).map do |symbol_data|
+ HeadMusic::MusicalSymbol.new(symbol_data.slice(:ascii, :html_entity, :unicode))
+ end
end
end