Class: HeadMusic::Instruments::Instrument
- Inherits:
-
Object
- Object
- HeadMusic::Instruments::Instrument
- Includes:
- Named
- Defined in:
- lib/head_music/instruments/instrument.rb
Overview
A musical instrument with parent-based inheritance.
Instruments can inherit from parent instruments, allowing for a clean hierarchy where child instruments override specific attributes while inheriting others from their parents.
Examples: trumpet = HeadMusic::Instruments::Instrument.get(“trumpet”) clarinet_in_a = HeadMusic::Instruments::Instrument.get(“clarinet_in_a”) clarinet_in_a.parent # => clarinet clarinet_in_a.pitch_key # => “a” (own attribute) clarinet_in_a.family_key # => “clarinet” (inherited from parent)
Attributes: name_key: the primary identifier for the instrument parent_key: optional key referencing the parent instrument family_key: the instrument family (e.g., “clarinet”, “trumpet”) pitch_key: the pitch designation (e.g., “b_flat”, “a”, “c”) alias_name_keys: alternative names for the instrument range_categories: size/range classifications
Constant Summary collapse
- INSTRUMENTS =
YAML.load_file(File.("instruments.yml", __dir__)).freeze
- VARIANT_PATTERN =
Convert shorthand variant names to full form e.g., “trumpet_in_eb” -> “trumpet_in_e_flat” e.g., “clarinet_in_bb” -> “clarinet_in_b_flat”
/^(.+)_in_([a-g])([b#])$/i
Instance Attribute Summary collapse
-
#alias_name_keys ⇒ Object
readonly
Returns the value of attribute alias_name_keys.
-
#alias_name_keys ⇒ Object
included
from Named
readonly
Returns the value of attribute alias_name_keys.
-
#name_key ⇒ Object
readonly
Returns the value of attribute name_key.
-
#name_key ⇒ Object
included
from Named
readonly
Returns the value of attribute name_key.
-
#parent_key ⇒ Object
readonly
Returns the value of attribute parent_key.
-
#range_categories ⇒ Object
readonly
Returns the value of attribute range_categories.
Class Method Summary collapse
-
.all ⇒ Object
-
.find_valid_instrument(name) ⇒ Object
-
.get(name, variant_key = nil) ⇒ Instrument?
Factory method to get an Instrument instance.
-
.normalize_variant_name(name_str) ⇒ Object
private
Instance Method Summary collapse
-
#==(other) ⇒ Object
-
#alternate_tunings ⇒ Object
-
#classification_keys ⇒ Object
-
#default_variant ⇒ Object
-
#ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object
included
from Named
-
#family ⇒ Object
-
#family_key ⇒ Object
Attributes with parent chain resolution.
-
#initialize(name) ⇒ Instrument
constructor
private
A new instance of Instrument.
-
#initialize_data_from_record(record) ⇒ Object
private
-
#initialize_name ⇒ Object
private
-
#instrument_configurations ⇒ Object
Collect all instrument_configurations from self and ancestors.
-
#localized_name(locale_code: Locale::DEFAULT_CODE) ⇒ Object
included
from Named
-
#localized_name_in_default_locale ⇒ Object
included
from Named
private
-
#localized_name_in_locale_matching_language(locale) ⇒ Object
included
from Named
private
-
#localized_name_in_matching_locale(locale) ⇒ Object
included
from Named
private
-
#localized_names ⇒ Object
included
from Named
Returns an array of LocalizedName instances that are synonymous with the name.
-
#name(locale_code: Locale::DEFAULT_CODE) ⇒ Object
included
from Named
-
#name=(name) ⇒ Object
included
from Named
-
#notation(style: :default) ⇒ Object
Notation for this instrument in the given style (defaults to :default).
-
#orchestra_section_key ⇒ Object
-
#parent ⇒ Object
Parent instrument (for inheritance).
-
#pitch_designation ⇒ Object
Pitch designation as a Spelling object (for backward compatibility).
-
#pitch_key ⇒ Object
-
#pitch_key_to_designation ⇒ Object
private
Convert pitch_key (e.g., “b_flat”) to designation format (e.g., “Bb”).
-
#staff_profile ⇒ Object
-
#stringing ⇒ Object
-
#to_s ⇒ Object
-
#translation(locale = :en) ⇒ Object
-
#variants ⇒ Object
For backward compatibility with code that expects variants.
Constructor Details
#initialize(name) ⇒ Instrument (private)
Returns a new instance of Instrument.
181 182 183 184 185 186 187 188 189 190 |
# File 'lib/head_music/instruments/instrument.rb', line 181 def initialize(name) record = HeadMusic::Instruments::InstrumentCatalog.new(INSTRUMENTS).record_for(name) if record initialize_data_from_record(record) else # Mark as invalid - will be filtered out by get_by_name @name_key = nil self.name = name.to_s end end |
Instance Attribute Details
#alias_name_keys ⇒ Object (readonly)
Returns the value of attribute alias_name_keys.
29 30 31 |
# File 'lib/head_music/instruments/instrument.rb', line 29 def alias_name_keys @alias_name_keys end |
#alias_name_keys ⇒ Object (readonly) Originally defined in module Named
Returns the value of attribute alias_name_keys.
#name_key ⇒ Object (readonly)
Returns the value of attribute name_key.
29 30 31 |
# File 'lib/head_music/instruments/instrument.rb', line 29 def name_key @name_key end |
#name_key ⇒ Object (readonly) Originally defined in module Named
Returns the value of attribute name_key.
#parent_key ⇒ Object (readonly)
Returns the value of attribute parent_key.
29 30 31 |
# File 'lib/head_music/instruments/instrument.rb', line 29 def parent_key @parent_key end |
#range_categories ⇒ Object (readonly)
Returns the value of attribute range_categories.
29 30 31 |
# File 'lib/head_music/instruments/instrument.rb', line 29 def range_categories @range_categories end |
Class Method Details
.all ⇒ Object
52 53 54 55 56 |
# File 'lib/head_music/instruments/instrument.rb', line 52 def all HeadMusic::Instruments::InstrumentFamily.all # Ensure families are loaded first INSTRUMENTS.map { |key, _data| get(key) } @all ||= @instances.values.compact.sort_by { |instrument| instrument.name.downcase } end |
.find_valid_instrument(name) ⇒ Object
47 48 49 50 |
# File 'lib/head_music/instruments/instrument.rb', line 47 def find_valid_instrument(name) instrument = get_by_name(name) instrument&.name_key ? instrument : nil end |
.get(name, variant_key = nil) ⇒ Instrument?
Factory method to get an Instrument instance
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/head_music/instruments/instrument.rb', line 36 def get(name, variant_key = nil) return name if name.is_a?(self) name_str = name.to_s if variant_key find_valid_instrument("#{name_str}_#{variant_key}") || find_valid_instrument(name_str) else find_valid_instrument(name_str) || find_valid_instrument(normalize_variant_name(name_str)) end end |
.normalize_variant_name(name_str) ⇒ Object (private)
65 66 67 68 69 70 71 |
# File 'lib/head_music/instruments/instrument.rb', line 65 def normalize_variant_name(name_str) match = VARIANT_PATTERN.match(name_str.to_s) return name_str.to_s unless match suffix = (match[3] == "b") ? "flat" : "sharp" "#{match[1]}_in_#{match[2].downcase}_#{suffix}" end |
Instance Method Details
#==(other) ⇒ Object
140 141 142 143 144 |
# File 'lib/head_music/instruments/instrument.rb', line 140 def ==(other) return false unless other.is_a?(self.class) name_key == other.name_key end |
#alternate_tunings ⇒ Object
170 171 172 173 174 175 |
# File 'lib/head_music/instruments/instrument.rb', line 170 def alternate_tunings own_tunings = HeadMusic::Instruments::AlternateTuning.for_instrument(name_key) return own_tunings if own_tunings.any? parent&.alternate_tunings || [] end |
#classification_keys ⇒ Object
101 102 103 |
# File 'lib/head_music/instruments/instrument.rb', line 101 def classification_keys family&.classification_keys || [] end |
#default_variant ⇒ Object
155 156 157 |
# File 'lib/head_music/instruments/instrument.rb', line 155 def default_variant nil end |
#ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object Originally defined in module Named
#family ⇒ Object
91 92 93 94 95 |
# File 'lib/head_music/instruments/instrument.rb', line 91 def family return unless family_key HeadMusic::Instruments::InstrumentFamily.get(family_key) end |
#family_key ⇒ Object
Attributes with parent chain resolution
83 84 85 |
# File 'lib/head_music/instruments/instrument.rb', line 83 def family_key @family_key || parent&.family_key end |
#initialize_data_from_record(record) ⇒ Object (private)
192 193 194 195 196 197 198 199 200 201 |
# File 'lib/head_music/instruments/instrument.rb', line 192 def initialize_data_from_record(record) @name_key = record["name_key"].to_sym @parent_key = record["parent_key"]&.to_sym @family_key = record["family_key"] @pitch_key = record["pitch_key"] @alias_name_keys = record["alias_name_keys"] || [] @range_categories = record["range_categories"] || [] initialize_name end |
#initialize_name ⇒ Object (private)
203 204 205 206 207 |
# File 'lib/head_music/instruments/instrument.rb', line 203 def initialize_name self.name = HeadMusic::Instruments::InstrumentName.new( name_key: name_key, parent_key: parent_key, pitch_designation: pitch_key_to_designation ).to_s end |
#instrument_configurations ⇒ Object
Collect all instrument_configurations from self and ancestors
160 161 162 163 164 |
# File 'lib/head_music/instruments/instrument.rb', line 160 def instrument_configurations own_configs = HeadMusic::Instruments::InstrumentConfiguration.for_instrument(name_key) parent_configs = parent&.instrument_configurations || [] own_configs + parent_configs end |
#localized_name(locale_code: Locale::DEFAULT_CODE) ⇒ Object Originally defined in module Named
#localized_name_in_default_locale ⇒ Object (private) Originally defined in module Named
#localized_name_in_locale_matching_language(locale) ⇒ Object (private) Originally defined in module Named
#localized_name_in_matching_locale(locale) ⇒ Object (private) Originally defined in module Named
#localized_names ⇒ Object Originally defined in module Named
Returns an array of LocalizedName instances that are synonymous with the name.
#name(locale_code: Locale::DEFAULT_CODE) ⇒ Object Originally defined in module Named
#name=(name) ⇒ Object Originally defined in module Named
#notation(style: :default) ⇒ Object
Notation for this instrument in the given style (defaults to :default).
113 114 115 |
# File 'lib/head_music/instruments/instrument.rb', line 113 def notation(style: :default) HeadMusic::Notation::NotationStyle.get(style).notation_for(self) end |
#orchestra_section_key ⇒ Object
97 98 99 |
# File 'lib/head_music/instruments/instrument.rb', line 97 def orchestra_section_key family&.orchestra_section_key end |
#parent ⇒ Object
Parent instrument (for inheritance)
75 76 77 78 79 |
# File 'lib/head_music/instruments/instrument.rb', line 75 def parent return nil unless parent_key @parent ||= self.class.get(parent_key) end |
#pitch_designation ⇒ Object
Pitch designation as a Spelling object (for backward compatibility)
106 107 108 109 110 |
# File 'lib/head_music/instruments/instrument.rb', line 106 def pitch_designation return nil unless pitch_key @pitch_designation ||= HeadMusic::Rudiment::Spelling.get(pitch_key_to_designation) end |
#pitch_key ⇒ Object
87 88 89 |
# File 'lib/head_music/instruments/instrument.rb', line 87 def pitch_key @pitch_key || parent&.pitch_key end |
#pitch_key_to_designation ⇒ Object (private)
Convert pitch_key (e.g., “b_flat”) to designation format (e.g., “Bb”)
210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/head_music/instruments/instrument.rb', line 210 def pitch_key_to_designation return nil unless pitch_key pitch_key_str = pitch_key.to_s first_letter = pitch_key_str[0].upcase if pitch_key_str.end_with?("_flat") "#{first_letter}b" elsif pitch_key_str.end_with?("_sharp") "#{first_letter}#" else pitch_key_str.upcase end end |
#staff_profile ⇒ Object
130 131 132 |
# File 'lib/head_music/instruments/instrument.rb', line 130 def staff_profile @staff_profile ||= HeadMusic::Instruments::StaffProfile.new(self) end |
#stringing ⇒ Object
166 167 168 |
# File 'lib/head_music/instruments/instrument.rb', line 166 def stringing @stringing ||= HeadMusic::Instruments::Stringing.for_instrument(self) || parent&.stringing end |
#to_s ⇒ Object
146 147 148 |
# File 'lib/head_music/instruments/instrument.rb', line 146 def to_s name end |
#translation(locale = :en) ⇒ Object
134 135 136 137 138 |
# File 'lib/head_music/instruments/instrument.rb', line 134 def translation(locale = :en) return name unless name_key HeadMusic::Instruments::InstrumentName.translate(name_key, locale: locale, default: name) end |
#variants ⇒ Object
For backward compatibility with code that expects variants
151 152 153 |
# File 'lib/head_music/instruments/instrument.rb', line 151 def variants [] end |