Class: HeadMusic::Style::Guidelines::NotesSameLength

Inherits:
Annotation
  • Object
show all
Defined in:
lib/head_music/style/guidelines/notes_same_length.rb

Overview

A counterpoint guideline

Constant Summary collapse

MESSAGE =
"Use consistent rhythmic unit."

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from HeadMusic::Style::Annotation

Instance Method Details

#acceptable_duration_of_last_note?Boolean (private)

Returns:

  • (Boolean)


44
45
46
47
48
49
50
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 44

def acceptable_duration_of_last_note?
  last_note.nil? ||
    [
      first_most_common_rhythmic_value.total_value,
      first_most_common_rhythmic_value.total_value * 2
    ].include?(last_note.rhythmic_value.total_value)
end

#all_but_last_noteObject (private)



52
53
54
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 52

def all_but_last_note
  notes[0..-2]
end

#all_wrong_length_notesObject (private)



30
31
32
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 30

def all_wrong_length_notes
  (wrong_length_notes + [wrong_length_last_note]).compact
end

#first_most_common_rhythmic_valueObject



12
13
14
15
16
17
18
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 12

def first_most_common_rhythmic_value
  @first_most_common_rhythmic_value ||= begin
    candidates = most_common_rhythmic_values
    first_match = notes.detect { |note| candidates.include?(note.rhythmic_value) }
    first_match&.rhythmic_value
  end
end

#marksObject



8
9
10
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 8

def marks
  HeadMusic::Style::Mark.for_each(all_wrong_length_notes)
end

#most_common_rhythmic_valuesObject



20
21
22
23
24
25
26
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 20

def most_common_rhythmic_values
  return [] if notes.empty?

  occurrences = occurrences_by_rhythmic_value
  highest_count = occurrences.values.max
  occurrences.select { |_rhythmic_value, count| count == highest_count }.keys
end

#occurrences_by_rhythmic_valueObject (private)



56
57
58
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 56

def occurrences_by_rhythmic_value
  rhythmic_values.each_with_object(Hash.new(0)) { |value, hash| hash[value] += 1 }
end

#rhythmic_valuesObject (private)



60
61
62
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 60

def rhythmic_values
  notes.map(&:rhythmic_value)
end

#wrong_length_last_noteObject (private)



40
41
42
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 40

def wrong_length_last_note
  last_note unless acceptable_duration_of_last_note?
end

#wrong_length_notesObject (private)



34
35
36
37
38
# File 'lib/head_music/style/guidelines/notes_same_length.rb', line 34

def wrong_length_notes
  all_but_last_note.reject do |note|
    note.rhythmic_value == first_most_common_rhythmic_value
  end
end