coltrane 2.2.1 → 3.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +16 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +25 -2
- data/README.md +3 -0
- data/bin/console +6 -2
- data/coltrane.gemspec +2 -1
- data/exe/coltrane +14 -224
- data/lib/coltrane.rb +3 -50
- data/lib/coltrane/commands.rb +14 -0
- data/lib/coltrane/commands/chords.rb +77 -0
- data/lib/coltrane/commands/command.rb +45 -0
- data/lib/coltrane/commands/common_chords.rb +33 -0
- data/lib/coltrane/commands/errors.rb +44 -0
- data/lib/coltrane/commands/find_progression.rb +28 -0
- data/lib/coltrane/commands/find_scale.rb +39 -0
- data/lib/coltrane/commands/notes.rb +44 -0
- data/lib/coltrane/commands/progression.rb +27 -0
- data/lib/{cli → coltrane/commands}/representation.rb +0 -0
- data/lib/coltrane/commands/scale.rb +46 -0
- data/lib/coltrane/renderers.rb +6 -0
- data/lib/coltrane/renderers/renderer.rb +42 -0
- data/lib/coltrane/renderers/text_renderer.rb +23 -0
- data/lib/coltrane/renderers/text_renderer/array_drawer.rb +45 -0
- data/lib/coltrane/renderers/text_renderer/base_drawer.rb +20 -0
- data/lib/coltrane/renderers/text_renderer/hash_drawer.rb +16 -0
- data/lib/coltrane/renderers/text_renderer/representation_guitar_chord_drawer.rb +95 -0
- data/lib/coltrane/renderers/text_renderer/representation_guitar_note_set_drawer.rb +76 -0
- data/lib/coltrane/renderers/text_renderer/representation_piano_note_set_drawer.rb +49 -0
- data/lib/coltrane/renderers/text_renderer/theory_chord_drawer.rb +14 -0
- data/lib/coltrane/renderers/text_renderer/theory_note_set_drawer.rb +17 -0
- data/lib/coltrane/renderers/text_renderer/theory_progression_drawer.rb +13 -0
- data/lib/coltrane/renderers/text_renderer/theory_progression_set_drawer.rb +22 -0
- data/lib/coltrane/renderers/text_renderer/theory_scale_drawer.rb +13 -0
- data/lib/coltrane/renderers/text_renderer/theory_scale_set_drawer.rb +27 -0
- data/lib/coltrane/representation.rb +12 -0
- data/lib/coltrane/representation/guitar.rb +34 -0
- data/lib/coltrane/representation/guitar/chord.rb +180 -0
- data/lib/coltrane/representation/guitar/note.rb +26 -0
- data/lib/coltrane/representation/guitar/note_set.rb +35 -0
- data/lib/coltrane/representation/guitar/string.rb +31 -0
- data/lib/coltrane/representation/guitar_like_instruments.rb +21 -0
- data/lib/coltrane/representation/piano.rb +36 -0
- data/lib/coltrane/representation/piano/note_set.rb +22 -0
- data/lib/{coltrane_synth.rb → coltrane/synth.rb.rb} +0 -0
- data/lib/{coltrane_synth → coltrane/synth}/base.rb +0 -0
- data/lib/{coltrane_synth → coltrane/synth}/synth.rb +0 -0
- data/lib/coltrane/theory.rb +54 -0
- data/lib/coltrane/theory/cadence.rb +9 -0
- data/lib/coltrane/{changes.rb → theory/changes.rb} +0 -0
- data/lib/coltrane/theory/chord.rb +101 -0
- data/lib/coltrane/theory/chord_quality.rb +113 -0
- data/lib/coltrane/theory/chord_substitutions.rb +11 -0
- data/lib/coltrane/theory/circle_of_fifths.rb +33 -0
- data/lib/coltrane/theory/classic_scales.rb +113 -0
- data/lib/coltrane/theory/diatonic_scale.rb +38 -0
- data/lib/coltrane/theory/errors.rb +97 -0
- data/lib/coltrane/theory/frequency.rb +52 -0
- data/lib/coltrane/theory/frequency_interval.rb +83 -0
- data/lib/coltrane/theory/interval.rb +209 -0
- data/lib/coltrane/theory/interval_class.rb +212 -0
- data/lib/coltrane/theory/interval_sequence.rb +157 -0
- data/lib/coltrane/theory/key.rb +18 -0
- data/lib/coltrane/{mode.rb → theory/mode.rb} +0 -0
- data/lib/coltrane/theory/notable_progressions.rb +30 -0
- data/lib/coltrane/theory/note.rb +104 -0
- data/lib/coltrane/theory/note_set.rb +101 -0
- data/lib/coltrane/theory/pitch.rb +94 -0
- data/lib/coltrane/theory/pitch_class.rb +154 -0
- data/lib/coltrane/theory/progression.rb +81 -0
- data/lib/coltrane/theory/progression_set.rb +18 -0
- data/lib/coltrane/{qualities.rb → theory/qualities.rb} +0 -0
- data/lib/coltrane/theory/roman_chord.rb +114 -0
- data/lib/coltrane/theory/scale.rb +161 -0
- data/lib/coltrane/theory/scale_search_result.rb +6 -0
- data/lib/coltrane/theory/scale_set.rb +40 -0
- data/lib/coltrane/theory/voicing.rb +41 -0
- data/lib/coltrane/version.rb +1 -1
- metadata +88 -63
- data/bin/rails +0 -17
- data/data/qualities.yml +0 -83
- data/db/cache.sqlite3 +0 -0
- data/db/cache_test.sqlite3 +0 -0
- data/db/config.yml +0 -11
- data/lib/cli.rb +0 -24
- data/lib/cli/bass_guitar.rb +0 -12
- data/lib/cli/chord.rb +0 -39
- data/lib/cli/config.rb +0 -39
- data/lib/cli/errors.rb +0 -46
- data/lib/cli/guitar.rb +0 -67
- data/lib/cli/guitar_chords.rb +0 -122
- data/lib/cli/notes.rb +0 -20
- data/lib/cli/piano.rb +0 -57
- data/lib/cli/scale.rb +0 -53
- data/lib/cli/text.rb +0 -16
- data/lib/cli/ukulele.rb +0 -14
- data/lib/coltrane/cache.rb +0 -43
- data/lib/coltrane/cadence.rb +0 -7
- data/lib/coltrane/chord.rb +0 -89
- data/lib/coltrane/chord_quality.rb +0 -111
- data/lib/coltrane/chord_substitutions.rb +0 -9
- data/lib/coltrane/circle_of_fifths.rb +0 -31
- data/lib/coltrane/classic_scales.rb +0 -94
- data/lib/coltrane/diatonic_scale.rb +0 -36
- data/lib/coltrane/errors.rb +0 -95
- data/lib/coltrane/frequency.rb +0 -50
- data/lib/coltrane/frequency_interval.rb +0 -81
- data/lib/coltrane/interval.rb +0 -208
- data/lib/coltrane/interval_class.rb +0 -210
- data/lib/coltrane/interval_sequence.rb +0 -155
- data/lib/coltrane/key.rb +0 -16
- data/lib/coltrane/notable_progressions.rb +0 -28
- data/lib/coltrane/note.rb +0 -98
- data/lib/coltrane/note_set.rb +0 -89
- data/lib/coltrane/pitch.rb +0 -92
- data/lib/coltrane/pitch_class.rb +0 -148
- data/lib/coltrane/progression.rb +0 -74
- data/lib/coltrane/roman_chord.rb +0 -112
- data/lib/coltrane/scale.rb +0 -154
- data/lib/coltrane/unordered_interval_class.rb +0 -7
- data/lib/coltrane/voicing.rb +0 -39
- data/lib/coltrane_game/question.rb +0 -7
- data/lib/coltrane_instruments.rb +0 -7
- data/lib/coltrane_instruments/guitar.rb +0 -10
- data/lib/coltrane_instruments/guitar/base.rb +0 -29
- data/lib/coltrane_instruments/guitar/chord.rb +0 -170
- data/lib/coltrane_instruments/guitar/note.rb +0 -24
- data/lib/coltrane_instruments/guitar/string.rb +0 -29
- data/lib/os.rb +0 -21
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'paint'
|
2
|
+
require 'color'
|
3
|
+
|
4
|
+
require 'coltrane/renderers/text_renderer/base_drawer'
|
5
|
+
require 'coltrane/renderers/text_renderer/array_drawer'
|
6
|
+
require 'coltrane/renderers/text_renderer/hash_drawer'
|
7
|
+
require 'coltrane/renderers/text_renderer/theory_note_set_drawer'
|
8
|
+
require 'coltrane/renderers/text_renderer/theory_chord_drawer'
|
9
|
+
require 'coltrane/renderers/text_renderer/theory_scale_drawer'
|
10
|
+
require 'coltrane/renderers/text_renderer/theory_scale_set_drawer'
|
11
|
+
require 'coltrane/renderers/text_renderer/theory_progression_drawer'
|
12
|
+
require 'coltrane/renderers/text_renderer/theory_progression_set_drawer'
|
13
|
+
require 'coltrane/renderers/text_renderer/representation_guitar_note_set_drawer'
|
14
|
+
require 'coltrane/renderers/text_renderer/representation_guitar_chord_drawer'
|
15
|
+
require 'coltrane/renderers/text_renderer/representation_piano_note_set_drawer'
|
16
|
+
|
17
|
+
module Coltrane
|
18
|
+
module Renderers
|
19
|
+
module TextRenderer
|
20
|
+
extend Renderer
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class ArrayDrawer < BaseDrawer
|
5
|
+
alias array model
|
6
|
+
|
7
|
+
def render
|
8
|
+
public_send("render_#{layout}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def renders
|
12
|
+
@renders ||= array.map {|it| TextRenderer.render(it, **options) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def render_vertical
|
16
|
+
renders.join("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_horizontal
|
20
|
+
array
|
21
|
+
.each_slice(per_row)
|
22
|
+
.map { |row|
|
23
|
+
row
|
24
|
+
.map { |element|
|
25
|
+
TextRenderer.render(element, **options)
|
26
|
+
.split("\n")
|
27
|
+
.yield_self { |lines|
|
28
|
+
lines
|
29
|
+
.map { |l| l.gsub(/\e\[(\d+)(;\d+)*m/, '').size }
|
30
|
+
.max
|
31
|
+
.yield_self { |column_w|
|
32
|
+
lines
|
33
|
+
.map { |l| l.ljust(column_w) }
|
34
|
+
.+([' ' * column_w])
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
.transpose
|
39
|
+
.map(&:join)
|
40
|
+
}.join("\n")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class BaseDrawer
|
5
|
+
include Paint
|
6
|
+
include Color
|
7
|
+
|
8
|
+
attr_reader :model, :options, :flavor, :layout, :per_row
|
9
|
+
|
10
|
+
def initialize(model, **options)
|
11
|
+
@model = model
|
12
|
+
@options = options
|
13
|
+
@flavor = options[:flavor] || :notes
|
14
|
+
@layout = options[:layout] || :vertical
|
15
|
+
@per_row = options[:per_row] || 4
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coltrane
|
4
|
+
module Renderers
|
5
|
+
module TextRenderer
|
6
|
+
class RepresentationGuitarChordDrawer < BaseDrawer
|
7
|
+
alias chord model
|
8
|
+
|
9
|
+
def chord_height
|
10
|
+
chord.max_fret_span
|
11
|
+
end
|
12
|
+
|
13
|
+
def guitar
|
14
|
+
chord.guitar
|
15
|
+
end
|
16
|
+
|
17
|
+
def render
|
18
|
+
render_top(chord) +
|
19
|
+
(chord.lowest_fret..chord.lowest_fret + chord_height)
|
20
|
+
.each_with_index.reduce('') do |memo1, (f, y)|
|
21
|
+
memo1 +
|
22
|
+
' ' +
|
23
|
+
(chord.guitar.strings.size * 2).times.map { |x| base_color border(x, y) }.join('') +
|
24
|
+
"\n" +
|
25
|
+
chord.guitar.strings.reduce(base_color(f.to_s.ljust(2, ' '))) do |memo2, s|
|
26
|
+
memo2 +
|
27
|
+
' ' +
|
28
|
+
render_note(chord.guitar_notes.select do |n|
|
29
|
+
n.string == s && n.fret == f
|
30
|
+
end.any?)
|
31
|
+
end +
|
32
|
+
" \n"
|
33
|
+
end + ' ' +
|
34
|
+
(chord.guitar.strings.size * 2).times.map do |x|
|
35
|
+
base_color border(x, chord_height + 1)
|
36
|
+
end.join('')
|
37
|
+
end
|
38
|
+
|
39
|
+
def border(x, y)
|
40
|
+
edge = [guitar.tuning.size * 2 - 2, chord_height + 1]
|
41
|
+
x_on_start = x == 0
|
42
|
+
y_on_start = y == 0
|
43
|
+
x_on_edge = x == edge[0]
|
44
|
+
y_on_edge = y == edge[1]
|
45
|
+
x_on_middle = (0...edge[0]).cover?(x)
|
46
|
+
y_on_middle = (0...edge[1]).cover?(y)
|
47
|
+
|
48
|
+
if x_on_start && y_on_start then '┍'
|
49
|
+
elsif x_on_middle && y_on_start then x.odd? ? '━' : '┯'
|
50
|
+
elsif x_on_edge && y_on_start then '┑'
|
51
|
+
elsif x_on_start && y_on_middle then '┝'
|
52
|
+
elsif x_on_middle && y_on_middle then x.odd? ? '━' : '┿'
|
53
|
+
elsif x_on_edge && y_on_middle then '┥'
|
54
|
+
elsif x_on_start && y_on_edge then '┕'
|
55
|
+
elsif x_on_middle && y_on_edge then x.odd? ? '━' : '┷'
|
56
|
+
elsif x_on_edge && y_on_edge then '┙'
|
57
|
+
else ' '
|
58
|
+
end
|
59
|
+
# puts edge.inspect
|
60
|
+
# "#{x},#{y} "
|
61
|
+
end
|
62
|
+
|
63
|
+
def base_color(str)
|
64
|
+
Paint[str, '#6A4AC2']
|
65
|
+
end
|
66
|
+
|
67
|
+
def highlight(str)
|
68
|
+
Paint[str, '#E67831']
|
69
|
+
end
|
70
|
+
|
71
|
+
def alt(str)
|
72
|
+
Paint[str, '#2DD380']
|
73
|
+
end
|
74
|
+
|
75
|
+
def render_top(chord)
|
76
|
+
chord.guitar.strings.reduce(' ') do |memo, s|
|
77
|
+
memo +
|
78
|
+
if chord.guitar_notes.select do |n|
|
79
|
+
n.string == s && n.fret == 0 end.any?
|
80
|
+
highlight '⬤ '
|
81
|
+
elsif chord.guitar_notes.select { |n| n.string == s && n.fret.nil? }.any?
|
82
|
+
alt 'x '
|
83
|
+
else
|
84
|
+
' '
|
85
|
+
end
|
86
|
+
end + "\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
def render_note(found)
|
90
|
+
found ? highlight('⬤') : base_color('│')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class RepresentationGuitarNoteSetDrawer < BaseDrawer
|
5
|
+
alias guitar_notes model
|
6
|
+
|
7
|
+
def guitar
|
8
|
+
@guitar ||= guitar_notes.guitar
|
9
|
+
end
|
10
|
+
|
11
|
+
def frets
|
12
|
+
guitar.frets
|
13
|
+
end
|
14
|
+
|
15
|
+
def render
|
16
|
+
[render_notes, render_special_frets].join("\n" * 2)
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_notes
|
20
|
+
guitar_notes.strings.map.with_index.map do |string, str_i|
|
21
|
+
Array.new(frets + 2) do |i|
|
22
|
+
if i.zero?
|
23
|
+
Paint[
|
24
|
+
string[:pitch].pitch_class.name,
|
25
|
+
HSL.new(140 + str_i * 20, 50, 50).html
|
26
|
+
]
|
27
|
+
else
|
28
|
+
(i - 1)
|
29
|
+
.yield_self { |fret|
|
30
|
+
(string[:pitch] + fret)
|
31
|
+
.yield_self { |pitch|
|
32
|
+
if guitar_notes.notes.include?(pitch.pitch_class)
|
33
|
+
place_mark(pitch.pitch_class)
|
34
|
+
else
|
35
|
+
place_empty(str_i)
|
36
|
+
end
|
37
|
+
}
|
38
|
+
.yield_self { |mark| mark + (fret.zero? ? (' |') : '') }
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end.join(' ')
|
42
|
+
end.join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_special_frets
|
46
|
+
' ' +
|
47
|
+
Array.new(frets + 2) do |fret|
|
48
|
+
m = guitar.special_frets.include?(fret) ? fret.to_s.rjust(2, 0.to_s) : ' '
|
49
|
+
"#{m}#{' ' if fret.zero?}"
|
50
|
+
end.join(' ')
|
51
|
+
end
|
52
|
+
|
53
|
+
def place_empty(str_i)
|
54
|
+
Paint['--', HSL.new(180 + str_i * 3, 50, 30).html]
|
55
|
+
end
|
56
|
+
|
57
|
+
def place_mark(note)
|
58
|
+
mark = case flavor
|
59
|
+
when :notes then note.pretty_name.ljust(2, ' ')
|
60
|
+
when :intervals then (guitar_notes.root - note).name.ljust(2, '-')
|
61
|
+
when :degrees then guitar_notes.notes.degree(note).to_s.rjust(2, '0')
|
62
|
+
when :marks then ' ' # '◼◼'
|
63
|
+
else raise WrongFlavorError
|
64
|
+
end
|
65
|
+
|
66
|
+
base_hue = (180 + note.integer * 10) % 360 # + 260
|
67
|
+
Paint[
|
68
|
+
mark,
|
69
|
+
HSL.new(0, 0, 100).html,
|
70
|
+
HSL.new(base_hue, 100, 30).html
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class RepresentationPianoNoteSetDrawer < BaseDrawer
|
5
|
+
alias note_set model
|
6
|
+
|
7
|
+
PIANO_TEMPLATE = <<~ASCII
|
8
|
+
┌─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─╥─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─┐
|
9
|
+
│ │ ││ │ ║ │ ││ ││ │ ║ │ ││ │ ║ │ ││ ││ │ │
|
10
|
+
│ │X││X│ ║ │X││X││X│ ║ │X││X│ ║ │X││X││X│ │
|
11
|
+
│ │X││X│ ║ │X││X││X│ ║ │X││X│ ║ │X││X││X│ │
|
12
|
+
│ ┕╥┙┕╥┙ ║ ┕╥┙┕╥┙┕╥┙ ║ ┕╥┙┕╥┙ ║ ┕╥┙┕╥┙┕╥┙ │
|
13
|
+
│ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ │
|
14
|
+
│XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX│
|
15
|
+
└──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──┘
|
16
|
+
ASCII
|
17
|
+
|
18
|
+
def render
|
19
|
+
PIANO_TEMPLATE.each_line.map.each_with_index do |l, ln|
|
20
|
+
case ln
|
21
|
+
when 2, 3 then replace_x(l, Representation::Piano.black_notes, 1, ln - 2)
|
22
|
+
when 6 then replace_x(l, Representation::Piano.white_notes, 2)
|
23
|
+
else l
|
24
|
+
end
|
25
|
+
end.join
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def replace_x(line, notes, size, index = 0)
|
31
|
+
line.gsub('X' * size).with_index do |_match, i|
|
32
|
+
note = notes[i % notes.size]
|
33
|
+
next ' ' * size unless note_set.include?(note)
|
34
|
+
Paint[replacer(note)[size == 2 ? 0..2 : index], 'red']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def replacer(note)
|
39
|
+
case flavor
|
40
|
+
when :intervals then (note_set.root - note).name
|
41
|
+
when :marks then '◼ '
|
42
|
+
when :degrees then note_set.notes.degree(note).to_s.rjust(2, '0')
|
43
|
+
when :notes then note.pretty_name.to_s.ljust(2, "\u266E")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class TheoryNoteSetDrawer < BaseDrawer
|
5
|
+
def render
|
6
|
+
case flavor
|
7
|
+
when :marks, :notes, :degrees
|
8
|
+
model.pretty_names.join(' ')
|
9
|
+
when :intervals
|
10
|
+
model.map { |n| (model.first - n).name }.join(' ')
|
11
|
+
else raise WrongFlavorError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class TheoryProgressionSetDrawer < BaseDrawer
|
5
|
+
alias progression_set model
|
6
|
+
|
7
|
+
def render
|
8
|
+
progression_set.map do |progression|
|
9
|
+
"#{progression.notation.ljust(notation_width + 1, ' ')} in " \
|
10
|
+
"#{progression.scale} (#{progression.notes_out.size} notes out)"
|
11
|
+
end
|
12
|
+
.join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
def notation_width
|
16
|
+
@notation_width ||=
|
17
|
+
progression_set.map(&:notation).map(&:size).max
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module Renderers
|
3
|
+
module TextRenderer
|
4
|
+
class TheoryScaleSetDrawer < BaseDrawer
|
5
|
+
alias scale_set model
|
6
|
+
|
7
|
+
def render
|
8
|
+
output = []
|
9
|
+
scale_width = scale_set.results.keys.map(&:size).max
|
10
|
+
scale_set.results.each do |name, scales_by_tone|
|
11
|
+
output << name.ljust(scale_width + 1, ' ')
|
12
|
+
scales_by_tone.each do |tone_number, notes|
|
13
|
+
p = (notes.size.to_f / scale_set.searched_notes.size) * 100
|
14
|
+
l = p == 100 ? p : (p + 20) * 0.4
|
15
|
+
und = p == 100 ? :underline : nil
|
16
|
+
color = Color::HSL.new(30, p, l / 2).html
|
17
|
+
output << Paint["#{Theory::Note[tone_number].name}(#{notes.size})", color, und]
|
18
|
+
output << ' '
|
19
|
+
end
|
20
|
+
output << "\n"
|
21
|
+
end
|
22
|
+
output.join
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|