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) ⇒ 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.
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/head_music/instruments/instrument.rb', line 176 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
47 48 49 50 51 |
# File 'lib/head_music/instruments/instrument.rb', line 47 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
42 43 44 45 |
# File 'lib/head_music/instruments/instrument.rb', line 42 def find_valid_instrument(name) instrument = get_by_name(name) instrument&.name_key ? instrument : nil end |
.get(name) ⇒ Instrument?
Factory method to get an Instrument instance
35 36 37 38 39 40 |
# File 'lib/head_music/instruments/instrument.rb', line 35 def get(name) return name if name.is_a?(self) name_str = name.to_s find_valid_instrument(name_str) || find_valid_instrument(normalize_variant_name(name_str)) end |
.normalize_variant_name(name_str) ⇒ Object (private)
60 61 62 63 64 65 66 |
# File 'lib/head_music/instruments/instrument.rb', line 60 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
135 136 137 138 139 |
# File 'lib/head_music/instruments/instrument.rb', line 135 def ==(other) return false unless other.is_a?(self.class) name_key == other.name_key end |
#alternate_tunings ⇒ Object
165 166 167 168 169 170 |
# File 'lib/head_music/instruments/instrument.rb', line 165 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
96 97 98 |
# File 'lib/head_music/instruments/instrument.rb', line 96 def classification_keys family&.classification_keys || [] end |
#default_variant ⇒ Object
150 151 152 |
# File 'lib/head_music/instruments/instrument.rb', line 150 def default_variant nil end |
#ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object Originally defined in module Named
#family ⇒ Object
86 87 88 89 90 |
# File 'lib/head_music/instruments/instrument.rb', line 86 def family return unless family_key HeadMusic::Instruments::InstrumentFamily.get(family_key) end |
#family_key ⇒ Object
Attributes with parent chain resolution
78 79 80 |
# File 'lib/head_music/instruments/instrument.rb', line 78 def family_key @family_key || parent&.family_key end |
#initialize_data_from_record(record) ⇒ Object (private)
187 188 189 190 191 192 193 194 195 196 |
# File 'lib/head_music/instruments/instrument.rb', line 187 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)
198 199 200 201 202 |
# File 'lib/head_music/instruments/instrument.rb', line 198 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
155 156 157 158 159 |
# File 'lib/head_music/instruments/instrument.rb', line 155 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).
108 109 110 |
# File 'lib/head_music/instruments/instrument.rb', line 108 def notation(style: :default) HeadMusic::Notation::NotationStyle.get(style).notation_for(self) end |
#orchestra_section_key ⇒ Object
92 93 94 |
# File 'lib/head_music/instruments/instrument.rb', line 92 def orchestra_section_key family&.orchestra_section_key end |
#parent ⇒ Object
Parent instrument (for inheritance)
70 71 72 73 74 |
# File 'lib/head_music/instruments/instrument.rb', line 70 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)
101 102 103 104 105 |
# File 'lib/head_music/instruments/instrument.rb', line 101 def pitch_designation return nil unless pitch_key @pitch_designation ||= HeadMusic::Rudiment::Spelling.get(pitch_key_to_designation) end |
#pitch_key ⇒ Object
82 83 84 |
# File 'lib/head_music/instruments/instrument.rb', line 82 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”)
205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/head_music/instruments/instrument.rb', line 205 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
125 126 127 |
# File 'lib/head_music/instruments/instrument.rb', line 125 def staff_profile @staff_profile ||= HeadMusic::Instruments::StaffProfile.new(self) end |
#stringing ⇒ Object
161 162 163 |
# File 'lib/head_music/instruments/instrument.rb', line 161 def stringing @stringing ||= HeadMusic::Instruments::Stringing.for_instrument(self) || parent&.stringing end |
#to_s ⇒ Object
141 142 143 |
# File 'lib/head_music/instruments/instrument.rb', line 141 def to_s name end |
#translation(locale = :en) ⇒ Object
129 130 131 132 133 |
# File 'lib/head_music/instruments/instrument.rb', line 129 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
146 147 148 |
# File 'lib/head_music/instruments/instrument.rb', line 146 def variants [] end |