Class: HeadMusic::Instruments::ScoreOrder
- Inherits:
-
Object
- Object
- HeadMusic::Instruments::ScoreOrder
- Includes:
- Named
- Defined in:
- lib/head_music/instruments/score_order.rb
Constant Summary collapse
- SCORE_ORDERS =
YAML.load_file(File.("score_orders.yml", __dir__)).freeze
- DEFAULT_ENSEMBLE_TYPE_KEY =
:orchestral
Instance Attribute Summary collapse
-
#alias_name_keys ⇒ Object
included
from Named
readonly
Returns the value of attribute alias_name_keys.
-
#ensemble_type_key ⇒ Object
readonly
Returns the value of attribute ensemble_type_key.
-
#name_key ⇒ Object
included
from Named
readonly
Returns the value of attribute name_key.
-
#sections ⇒ Object
readonly
Returns the value of attribute sections.
Class Method Summary collapse
- .get(ensemble_type) ⇒ Object
- .in_band_order(instruments) ⇒ Object
- .in_orchestral_order(instruments) ⇒ Object
Instance Method Summary collapse
-
#build_section_index ⇒ Object
private
A key listed twice -- two trumpets in a quintet -- keeps the last position, which is where the section still ends.
- #ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object included from Named
- #entry_by_family(instrument) ⇒ Object private
- #entry_by_name_key(instrument) ⇒ Object private
- #entry_by_normalized_name(instrument) ⇒ Object private
- #entry_for(instrument) ⇒ Object private
-
#find_entry(instrument) ⇒ Object
private
An entry is a Hash, so a nil lookup safely means "absent".
- #find_position_with_transposition(instrument) ⇒ Object private
-
#group(instruments) ⇒ Object
The same instruments as #order, split into their sections.
-
#initialize(ensemble_type_key = DEFAULT_ENSEMBLE_TYPE_KEY) ⇒ ScoreOrder
constructor
private
A new instance of ScoreOrder.
- #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
- #normalize_inputs(instruments) ⇒ Object private
- #normalize_to_instrument(input) ⇒ Object private
- #order(instruments) ⇒ Object
- #partition_by_known_position(instrument_objects) ⇒ Object private
-
#position_of(instrument) ⇒ Object
Where the instrument sits in the score, counting from the top, or nil where this order does not know it.
-
#section_index ⇒ Object
private
One index behind both the ordering and the grouping, so the two cannot disagree about where an instrument belongs.
-
#section_key_of(instrument) ⇒ Object
Which section the instrument belongs to -- what a score brackets together.
- #sort_known(known) ⇒ Object private
Constructor Details
#initialize(ensemble_type_key = DEFAULT_ENSEMBLE_TYPE_KEY) ⇒ ScoreOrder (private)
Returns a new instance of ScoreOrder.
59 60 61 62 63 64 65 |
# File 'lib/head_music/instruments/score_order.rb', line 59 def initialize(ensemble_type_key = DEFAULT_ENSEMBLE_TYPE_KEY) @ensemble_type_key = ensemble_type_key.to_sym data = SCORE_ORDERS[ensemble_type_key.to_s] @sections = data["sections"] || [] self.name = data["name"] || ensemble_type_key.to_s.tr("_", " ").capitalize end |
Instance Attribute Details
#alias_name_keys ⇒ Object (readonly) Originally defined in module Named
Returns the value of attribute alias_name_keys.
#ensemble_type_key ⇒ Object (readonly)
Returns the value of attribute ensemble_type_key.
10 11 12 |
# File 'lib/head_music/instruments/score_order.rb', line 10 def ensemble_type_key @ensemble_type_key end |
#name_key ⇒ Object (readonly) Originally defined in module Named
Returns the value of attribute name_key.
#sections ⇒ Object (readonly)
Returns the value of attribute sections.
10 11 12 |
# File 'lib/head_music/instruments/score_order.rb', line 10 def sections @sections end |
Class Method Details
.get(ensemble_type) ⇒ Object
12 13 14 15 16 17 18 |
# File 'lib/head_music/instruments/score_order.rb', line 12 def self.get(ensemble_type) @instances ||= {} key = HeadMusic::Utilities::HashKey.for(ensemble_type) return unless SCORE_ORDERS.key?(key.to_s) @instances[key] ||= new(key) end |
.in_band_order(instruments) ⇒ Object
24 25 26 |
# File 'lib/head_music/instruments/score_order.rb', line 24 def self.in_band_order(instruments) get(:band).order(instruments) end |
.in_orchestral_order(instruments) ⇒ Object
20 21 22 |
# File 'lib/head_music/instruments/score_order.rb', line 20 def self.in_orchestral_order(instruments) get(:orchestral).order(instruments) end |
Instance Method Details
#build_section_index ⇒ Object (private)
A key listed twice -- two trumpets in a quintet -- keeps the last position, which is where the section still ends.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/head_music/instruments/score_order.rb', line 112 def build_section_index index = {} position = 0 sections.each do |section| section_key = section["section_key"]&.to_sym instruments = section["instruments"] || [] instruments.each do |instrument_key| index[instrument_key.to_s] = {position: position, section_key: section_key} position += 1 end end index end |
#ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object Originally defined in module Named
#entry_by_family(instrument) ⇒ Object (private)
141 142 143 144 145 146 147 148 149 |
# File 'lib/head_music/instruments/score_order.rb', line 141 def entry_by_family(instrument) return nil unless instrument.family_key family_base = instrument.family_key.to_s instrument_key = instrument.name_key.to_s return nil unless instrument_key.include?(family_base) section_index[instrument_key] || section_index[family_base] end |
#entry_by_name_key(instrument) ⇒ Object (private)
135 136 137 138 139 |
# File 'lib/head_music/instruments/score_order.rb', line 135 def entry_by_name_key(instrument) return nil unless instrument.name_key section_index[instrument.name_key.to_s] end |
#entry_by_normalized_name(instrument) ⇒ Object (private)
151 152 153 |
# File 'lib/head_music/instruments/score_order.rb', line 151 def entry_by_normalized_name(instrument) section_index[HeadMusic::Utilities::Case.to_snake_case(instrument.name)] end |
#entry_for(instrument) ⇒ Object (private)
90 91 92 93 94 95 |
# File 'lib/head_music/instruments/score_order.rb', line 90 def entry_for(instrument) return nil if instrument.nil? normalized = normalize_to_instrument(instrument) normalized && find_entry(normalized) end |
#find_entry(instrument) ⇒ Object (private)
An entry is a Hash, so a nil lookup safely means "absent".
129 130 131 132 133 |
# File 'lib/head_music/instruments/score_order.rb', line 129 def find_entry(instrument) entry_by_name_key(instrument) || entry_by_family(instrument) || entry_by_normalized_name(instrument) end |
#find_position_with_transposition(instrument) ⇒ Object (private)
155 156 157 158 159 160 |
# File 'lib/head_music/instruments/score_order.rb', line 155 def find_position_with_transposition(instrument) entry = find_entry(instrument) return nil unless entry entry.merge(transposition: instrument.default_sounding_transposition || 0) end |
#group(instruments) ⇒ Object
The same instruments as #order, split into their sections. Instruments this order does not know come last, under a nil section key.
47 48 49 50 51 52 53 |
# File 'lib/head_music/instruments/score_order.rb', line 47 def group(instruments) # slice_when rather than chunk, which drops the nil-keyed run that the # unknown instruments belong to. order(instruments) .slice_when { |one, other| section_key_of(one) != section_key_of(other) } .map { |members| [section_key_of(members.first), members] } 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
#normalize_inputs(instruments) ⇒ Object (private)
67 68 69 70 |
# File 'lib/head_music/instruments/score_order.rb', line 67 def normalize_inputs(instruments) valid_inputs = instruments.compact.reject { |i| i.respond_to?(:empty?) && i.empty? } valid_inputs.map { |i| normalize_to_instrument(i) }.compact end |
#normalize_to_instrument(input) ⇒ Object (private)
97 98 99 100 101 102 |
# File 'lib/head_music/instruments/score_order.rb', line 97 def normalize_to_instrument(input) return input if input.is_a?(HeadMusic::Instruments::Instrument) return input if input.respond_to?(:name_key) && input.respond_to?(:family_key) HeadMusic::Instruments::Instrument.get(input) end |
#order(instruments) ⇒ Object
28 29 30 31 |
# File 'lib/head_music/instruments/score_order.rb', line 28 def order(instruments) known, unknown = partition_by_known_position(normalize_inputs(instruments)) sort_known(known) + unknown.sort_by(&:to_s) end |
#partition_by_known_position(instrument_objects) ⇒ Object (private)
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/head_music/instruments/score_order.rb', line 72 def partition_by_known_position(instrument_objects) known = [] unknown = [] instrument_objects.each do |instrument| position_info = find_position_with_transposition(instrument) if position_info known << [instrument, position_info] else unknown << instrument end end [known, unknown] end |
#position_of(instrument) ⇒ Object
Where the instrument sits in the score, counting from the top, or nil where this order does not know it.
35 36 37 |
# File 'lib/head_music/instruments/score_order.rb', line 35 def position_of(instrument) entry_for(instrument)&.fetch(:position) end |
#section_index ⇒ Object (private)
One index behind both the ordering and the grouping, so the two cannot disagree about where an instrument belongs.
106 107 108 |
# File 'lib/head_music/instruments/score_order.rb', line 106 def section_index @section_index ||= build_section_index end |
#section_key_of(instrument) ⇒ Object
Which section the instrument belongs to -- what a score brackets together. Nil where this order does not know the instrument.
41 42 43 |
# File 'lib/head_music/instruments/score_order.rb', line 41 def section_key_of(instrument) entry_for(instrument)&.fetch(:section_key) end |
#sort_known(known) ⇒ Object (private)
86 87 88 |
# File 'lib/head_music/instruments/score_order.rb', line 86 def sort_known(known) known.sort_by { |_, pos_info| [pos_info[:position], -pos_info[:transposition]] }.map(&:first) end |