wtf_chord 0.2.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 23feadfbf5375e890423135cc86a56d9b70af3e8
4
- data.tar.gz: aaa6a0d46fbeb51e715306da3d127b86816ed293
2
+ SHA256:
3
+ metadata.gz: 6b17613170273223d591f45e88733cf89449d8b872088496c7c569a7e053f4e0
4
+ data.tar.gz: 10460d448a476b45fd1ea0c96b6b418458f7c123b83f9bc8f8d45593e6fd1b36
5
5
  SHA512:
6
- metadata.gz: 711ef213b9ea7302e812c122fda26aee2bb305960a0a1fc3f687106948ea401dcfe17eaeac3972d9a42f6bdf22f6189d01255be790bf89194dbb5e6479a3d86c
7
- data.tar.gz: 4c081a0a57e196422c13fa0a40f671e55d2b39ad49f96678c8b87da277d5e242d4d38fd19924d7e0d920444cc290af7d5984208e75f8a1cbc4dbeeddd10e7547
6
+ metadata.gz: 37dc9a3b6f74eeb4615f8ff897982c0a4dff8577316415ce50cd9278968298d2c9a18d24ca885fde1f599c919b6547884983ab38e68f5ae49e33f6671436e8a9
7
+ data.tar.gz: 8d326d7047187a13e778af13928a3e5ac847e56c57109817feab09b17d00a29c2d56a33c9d98d23946ccde52fa5cc65e158f14ee71e59470bdb57ec319514ccb
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ ## 0.5.0 / 2016-08-17
2
+
3
+ * 2 major features
4
+ * Support chords with bass string mods (like Am/G)
5
+ * Add extra_complexity modifier
6
+
7
+ * 1 bug fixes:
8
+ * Fix fingering equality
9
+
10
+ * Add CHANGELOG.md
data/README.md CHANGED
@@ -31,13 +31,13 @@ Or install it yourself as:
31
31
 
32
32
  Finds fingerings of the requested chord.
33
33
 
34
- v0.2.1
34
+ v0.3.1
35
35
 
36
36
  Options:
37
37
  -h, --help Show command line help
38
38
  --version Show help/version info
39
39
  -n, --amount N Amount of fingering variants to output.
40
- (default: 3)
40
+ (default: 5)
41
41
  -o, --output FORMAT Output format.
42
42
  (default: default)
43
43
  -R, --[no-]rates Output fingering complexity rates
@@ -57,25 +57,25 @@ For example, to print two fingering variants of the `Dm` chord, just run:
57
57
  And you'll get the visual presentation of chords' fingerings:
58
58
 
59
59
  [ × × 0 2 3 1 ]
60
- ––––––––––––––––––
61
- | | | | |
62
- | | | | |
63
- | | | | |
60
+ ——————————————————
61
+ | | | | |
62
+ | | | | |
63
+ | | | | |
64
64
  | | | | | |
65
65
  | | | | | |
66
66
  | | | | | |
67
- ––––––––––––––––––
67
+ ——————————————————
68
68
  D A D F
69
69
 
70
70
  [ × 5 7 7 6 5 ]
71
- ––––––––––––––––––
72
- | | | | V
73
- | | | | |
74
- | | | |
71
+ ——————————————————
72
+ | | | | ◉ ← V
73
+ | | | | |
74
+ | | | |
75
75
  | | | | | |
76
76
  | | | | | |
77
77
  | | | | | |
78
- ––––––––––––––––––
78
+ ——————————————————
79
79
  D A D F A
80
80
 
81
81
  You can get simpler output, using the `--output` option:
@@ -1,68 +1,41 @@
1
1
  require 'wtf_chord/fingering'
2
+ require 'wtf_chord/fingerings_generator'
2
3
 
3
4
  module WTFChord
4
5
  class Chord
5
- MAX_DIST = 5
6
- MAX_FRET = 7
6
+ BASS_MATCH = /(?<=[\\\/])[A-H][b#]?(?=$)/
7
7
 
8
- attr_reader :pitch, :steps, :notes, :name
8
+ attr_reader :pitch, :steps, :notes, :name, :bass
9
9
 
10
10
  def initialize(note, name)
11
11
  @pitch = note.is_a?(Pitch) ? note : WTFChord.note(note)
12
12
  @name = "#{@pitch.key}#{name}".freeze
13
13
  @steps = Array(WTFChord.rules[name])
14
14
  @notes = @steps.map { |dist| (@pitch + dist).note }.tap(&:uniq!)
15
- end
16
15
 
17
- def inspect
18
- "#{name} (#{@notes.map(&:key) * ' - '})"
19
- end
20
-
21
- def fingerings(limit = 3)
22
- list = []
23
-
24
- (0..MAX_FRET).each do |from_fret|
25
- f = get_fingering(from_fret)
26
- next if list.include?(f)
27
- list << f if all_notes?(f.used_strings)
16
+ BASS_MATCH.match(@name) do |m|
17
+ @bass = WTFChord.note(m[0]).note
28
18
  end
29
-
30
- sort_fingerings(list, limit)
31
19
  end
32
20
 
33
- def get_fingering(from_fret = 0)
34
- to_fret = from_fret + MAX_DIST
35
- Fingering.new(GUITAR) do |f|
36
- f.strings.each do |s|
37
- fret = (from_fret..to_fret).detect { |dist| @notes.include?((s.original + dist).note) }
38
- fret ? s.hold_on(fret) : s.dead
39
- end
40
-
41
- adjust_fingering(f.used_strings[0], to_fret, 0) while should_adjust?(f.used_strings[0], 0)
42
- end
21
+ def fingerings(limit = nil)
22
+ FingeringsGenerator.new(self).call[0, limit || 5]
43
23
  end
44
24
 
45
- def all_notes?(strings)
46
- snotes = strings.map(&:note).tap(&:uniq!)
47
- @notes.all? { |n| snotes.include?(n) }
25
+ def third_tone
26
+ @third_tone ||= @notes[@steps.size > 3 ? 2 : -1]
48
27
  end
49
28
 
50
- def adjust_fingering(string, to_fret, i = 0)
51
- while string.fret < to_fret.pred
52
- string.hold_on(string.fret + 1)
53
- break if @notes.include?(string.note)
54
- end
55
-
56
- string.dead if !string.dead? && string.note != @notes[i]
29
+ def bass?
30
+ !!@bass
57
31
  end
58
32
 
59
- def should_adjust?(string, i = 0)
60
- string && string.note != @notes[i]
33
+ def original_bass
34
+ @notes[0]
61
35
  end
62
36
 
63
- def sort_fingerings(list, limit)
64
- list.sort_by!(&:complexity)
65
- list[0...limit].sort_by!(&:min_fret)
37
+ def inspect
38
+ "#{name} (#{@notes.map(&:key) * ' - '})"
66
39
  end
67
40
  end
68
41
  end
data/lib/wtf_chord/cli.rb CHANGED
@@ -7,14 +7,15 @@ module WTFChord
7
7
  include Methadone::CLILogging
8
8
 
9
9
  main do |name|
10
- chord = WTFChord.chord(name)
11
- fingerings = chord.fingerings(options['amount'])
12
- formatter = WTFChord::Formatter.new(options['output'], options['rates'])
10
+ chord = WTFChord.chord(name)
11
+ formatter = WTFChord::Formatter.new(options['output'], options['rates'])
13
12
 
14
13
  debug { "Output using formatter: #{formatter.formatter.to_s}\n" }
15
14
 
15
+ options['amount'] = 1 if options['output'] == 'piano'
16
+
16
17
  puts chord.inspect, nil
17
- formatter.(*fingerings)
18
+ puts formatter[*chord.fingerings(options['amount'])] * formatter.separator
18
19
  end
19
20
 
20
21
  version VERSION
@@ -31,7 +32,7 @@ module WTFChord
31
32
  ##
32
33
  # Options
33
34
  #
34
- options['amount'] = 3
35
+ options['amount'] = 5
35
36
  options['output'] = 'default'
36
37
  options['rates'] = false
37
38
 
@@ -6,19 +6,29 @@ module WTFChord
6
6
 
7
7
  def rate
8
8
  frets = @fingering.holded_strings.map(&:fret)
9
- barre = frets.uniq.keep_if { |o| frets.count(o) >= 2 }.min
10
- barre_strings = barre ? frets.count(barre).pred : 0
9
+ barre = frets.uniq.keep_if { |o| frets.count(o) >= 2 }
10
+ barre_strings = barre.min ? frets.count(barre.min).pred : 0
11
11
 
12
12
  base_rate = begin
13
- Rational(holded_strings - barre_strings, 6).to_f +
14
- Rational(finger_dist(frets), 5).to_f
13
+ Rational(holded_strings - barre_strings, 4).to_f +
14
+ Rational(finger_dist(@fingering.used_strings.map(&:fret)), 4).to_f
15
15
  end
16
16
 
17
+ base_rate += 0.5 if (holded_strings - barre_strings) > 4
18
+
17
19
  # p [@fingering, holded_strings, barre_strings]
18
20
 
19
- base_rate += 1 if (barre_strings > 2 || frets.uniq.size > 3) && complex_barre?(barre, frets)
21
+ if holded_strings > 4
22
+ uniq_frets = frets.uniq.size
23
+
24
+ if barre.size > 1 && uniq_frets == 3 && frets.count(barre.max) > barre_strings.next
25
+ base_rate += 1 if complex_barre?(barre.max, frets)
26
+ elsif barre_strings.next >= 2 || uniq_frets.size > 3
27
+ base_rate += 1 if complex_barre?(barre.min, frets)
28
+ end
29
+ end
20
30
 
21
- base_rate
31
+ base_rate + @fingering.extra_complexity
22
32
  end
23
33
 
24
34
  private
@@ -4,14 +4,18 @@ require 'wtf_chord/formatter'
4
4
 
5
5
  module WTFChord
6
6
  class Fingering < Fretboard
7
- def initialize(guitar)
7
+ attr_accessor :extra_complexity
8
+
9
+ def initialize(guitar, fingers = nil)
8
10
  @capo = guitar.capo
9
11
  @strings = guitar.strings.map(&:dup)
12
+ @extra_complexity = 0.0
13
+ set_fingers(fingers) if fingers.is_a?(Array)
10
14
  yield(self) if block_given?
11
15
  end
12
16
 
13
17
  def code
14
- @code ||= strings.map(&:code).pack("c*")
18
+ strings.map(&:code).pack("c*")
15
19
  end
16
20
 
17
21
  def == other
@@ -22,6 +26,14 @@ module WTFChord
22
26
  end
23
27
  end
24
28
 
29
+ def eql?(other)
30
+ super || self == other
31
+ end
32
+
33
+ def hash
34
+ strings.map(&:code).hash
35
+ end
36
+
25
37
  def complexity
26
38
  complexity_counter.rate
27
39
  end
@@ -42,6 +54,14 @@ module WTFChord
42
54
  @strings.reject(&:dead?)
43
55
  end
44
56
 
57
+ def find_used_string_for(note)
58
+ used = used_strings
59
+ if idx = used.index(note)
60
+ string = used[idx]
61
+ yield(strings.index(string), string)
62
+ end
63
+ end
64
+
45
65
  def min_fret
46
66
  holded_strings.min.fret
47
67
  end
@@ -0,0 +1,120 @@
1
+ module WTFChord
2
+ class Chord
3
+ end
4
+
5
+ class FingeringsGenerator < DelegateClass(Chord)
6
+ MAX_DIST = 5
7
+ MAX_FRET = 7
8
+
9
+ def fingerings
10
+ @fingerings ||= []
11
+ end
12
+
13
+ def call
14
+ fingerings.clear
15
+
16
+ (0...MAX_FRET).each do |from|
17
+ to = from + MAX_DIST
18
+ generate(from...to) do |variant|
19
+ fingerings << set_bass(variant) if filter_variant(variant)
20
+ end
21
+ end
22
+
23
+ fingerings.uniq!
24
+ fingerings.sort_by!(&:complexity)
25
+ end
26
+
27
+ private
28
+
29
+ def generate(fret_range)
30
+ combinations = WTFChord.guitar.strings.map.with_index do |s, index|
31
+ fret_range.
32
+ select { |dist| pitch = s.original + dist; has_note?(pitch) }.
33
+ tap { |frets| frets << nil if frets.size == 0 }
34
+ end
35
+
36
+ combinations.inject(&:product).each do |fingers|
37
+ fingers.flatten!
38
+
39
+ Fingering.new(WTFChord.guitar, fingers) do |variant|
40
+ adjust(variant)
41
+ yield(variant)
42
+ end
43
+ end
44
+ end
45
+
46
+ def filter_variant(variant)
47
+ used_strings = variant.used_strings
48
+ used_notes = used_strings.map(&:note)
49
+ tones_count = notes.map { |n| used_notes.count(n) }
50
+
51
+ !fingerings.include?(variant) &&
52
+ basetone?(used_strings[0]) &&
53
+ (
54
+ (third?(used_strings[1]) || third?(used_strings[2])) ||
55
+ (last?(used_strings[1]) || last?(used_strings[2]))
56
+ ) &&
57
+ all_notes?(used_notes) &&
58
+ used_notes.each_cons(2).none? { |(l, r)| l == r } &&
59
+ tones_count.all? { |n| tones_count[0] >= n || tones_count[notes.index(third_tone)] >= n } &&
60
+ variant.complexity <= 2.25
61
+ end
62
+
63
+ def adjust(fingering)
64
+ while (string = fingering.used_strings[0]) && !basetone?(string)
65
+ string.dead if !string.dead?
66
+ break if fingering.used_strings.size == 4
67
+ end
68
+ end
69
+
70
+ def set_bass(variant)
71
+ if bass?
72
+ variant.find_used_string_for(original_bass) do |idx, bass_string|
73
+ try_set_bass_on(variant, idx) or begin
74
+ 4.times do |i|
75
+ next if i == idx
76
+ if try_set_bass_on(variant, i)
77
+ bass_string.dead
78
+ break
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ variant
86
+ end
87
+
88
+ def try_set_bass_on(variant, idx)
89
+ bass_string = variant.strings[idx].dup
90
+ distance = bass_string.distance_to(bass)
91
+
92
+ if distance >= 0 && distance < 5 && (distance - variant.min_fret) > -3
93
+ variant.extra_complexity += 0.5 if distance < variant.min_fret
94
+ variant.strings[idx].hold_on(distance)
95
+ true
96
+ end
97
+ end
98
+
99
+ def all_notes?(used_notes)
100
+ notes.all? { |n| used_notes.include?(n) }
101
+ end
102
+
103
+ def has_note?(value)
104
+ value = value.note if !value.is_a?(Note) && value.respond_to?(:note)
105
+ notes.include?(value)
106
+ end
107
+
108
+ def basetone?(string)
109
+ string && string.note == notes[0]
110
+ end
111
+
112
+ def third?(string)
113
+ string && (string.note == third_tone)
114
+ end
115
+
116
+ def last?(string)
117
+ string && (string.note == notes[-1])
118
+ end
119
+ end
120
+ end
@@ -9,19 +9,21 @@ module WTFChord
9
9
  end
10
10
 
11
11
  def call(*fingerings)
12
- formatter.with_rates(@with_rates) do |f|
13
- puts (fingerings.map(&f) * f.separator)
14
- end
12
+ formatter.with_rates(@with_rates) { |f| fingerings.map(&f) }
15
13
  end
16
14
 
17
15
  alias :[] :call
18
16
 
17
+ def separator
18
+ formatter.separator
19
+ end
20
+
19
21
  def formatter
20
- WTFChord::Formatters.const_get(formatter_name)
22
+ Formatters.const_get(formatter_name)
21
23
  end
22
24
 
23
25
  def formatter?
24
- WTFChord::Formatters.const_defined?(formatter_name)
26
+ Formatters.const_defined?(formatter_name)
25
27
  end
26
28
 
27
29
  def formatter_name
@@ -31,6 +31,10 @@ module WTFChord
31
31
  def draw
32
32
  end
33
33
 
34
+ def keys
35
+ strings.reject(&:dead?).map(&:key)
36
+ end
37
+
34
38
  def with_rates?
35
39
  !!@with_rates
36
40
  end
@@ -1,25 +1,28 @@
1
+ require 'wtf_chord/helpers/roman_numbers_helper'
2
+
1
3
  module WTFChord
2
4
  module Formatters
3
5
  class Default < Base
4
6
  OPEN = "|".freeze
5
- HORIZ = "".freeze
7
+ HORIZ = "".freeze
6
8
  SPACE = " ".freeze
7
- BULL = "\u2022".freeze
8
- LATIN = %w(0 I II III IV V VI VII VIII IX X XII XIII).freeze
9
+ BULL = "\u25C9".freeze
9
10
  NEWLINE = "\n".freeze
11
+ COMPLEXITY_FORMAT = " (complexity: %.2f)".freeze
12
+ EMPTY_STRING = Array.new(FRETS, OPEN).freeze
10
13
 
11
- def self.separator
12
- "\n\n".freeze
13
- end
14
+ include RomanNumbersHelper
14
15
 
15
16
  def draw
16
- [
17
- "[ #{head} ]#{capo}",
18
- " #{border}",
19
- *fret_rows,
20
- " #{border}",
21
- " #{string_keys}#{rate}"
22
- ] * NEWLINE
17
+ <<-EOF.gsub(/^\s+\|/, '')
18
+ |[ #{head} ] #{capo}
19
+ | #{border}
20
+ #{fret_rows.map.with_index { |row, index|
21
+ " | #{row} #{roman_min_fret if index == 0}"
22
+ }.join("\n")}
23
+ | #{border}
24
+ | #{string_keys}#{rate}
25
+ EOF
23
26
  end
24
27
 
25
28
  private
@@ -29,11 +32,15 @@ module WTFChord
29
32
  end
30
33
 
31
34
  def capo
32
- " (capo #{to_latin @fret.capo})" if @fret.capo > 0
35
+ "(capo #{romanize(@fret.capo)})" if @fret.capo > 0
36
+ end
37
+
38
+ def roman_min_fret
39
+ " ← #{romanize(min_fret)}" if min_fret > 1
33
40
  end
34
41
 
35
42
  def rate
36
- " (complexity: %.2f)" % @fret.complexity if with_rates?
43
+ COMPLEXITY_FORMAT % @fret.complexity if with_rates?
37
44
  end
38
45
 
39
46
  def border
@@ -41,27 +48,21 @@ module WTFChord
41
48
  end
42
49
 
43
50
  def string_rows
44
- strings.map { |string| draw_string(string.fret) }
51
+ strings.map { |string| draw_string(string) }
45
52
  end
46
53
 
47
54
  def fret_rows
48
- string_rows.transpose.map! { |row| " #{row * SPACE} " }.tap do |rows|
49
- rows[0] << " #{to_latin min_fret}" if min_fret > 1
50
- end
55
+ return to_enum(__method__) unless block_given?
56
+ string_rows.transpose.each { |row| yield(row * SPACE) }
51
57
  end
52
58
 
53
59
  def string_keys
54
60
  strings.map { |s| s.dead? ? SPACE : "%-2s" % s.key } * " "
55
61
  end
56
62
 
57
- def to_latin(num)
58
- LATIN[num]
59
- end
60
-
61
- def draw_string(fret)
62
- Array.new(FRETS, OPEN).tap do |rows|
63
- rows[(fret - min_fret.pred).pred] = BULL if fret.to_i > 0
64
- end
63
+ def draw_string(string)
64
+ EMPTY_STRING.dup.
65
+ tap { |rows| rows[string.fret - min_fret] = BULL if string.holded? }
65
66
  end
66
67
  end
67
68
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "wtf_chord/keyboard"
4
+
5
+ module WTFChord
6
+ module Formatters
7
+ class Piano < Base
8
+ def draw
9
+ [
10
+ unique_notes.sort.join(" - "),
11
+ Keyboard.press(*unique_notes.map(&:position))
12
+ ].join("\n\n")
13
+ end
14
+
15
+ def unique_notes
16
+ strings.reject(&:dead?).each_with_object([[], []]) do |string, (positions, notes)|
17
+ unless positions.include?(string.note.position)
18
+ positions << string.note.position
19
+ notes << string.note
20
+ end
21
+ end[1]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -23,6 +23,14 @@ module WTFChord
23
23
  self
24
24
  end
25
25
 
26
+ def with_capo(capo)
27
+ capo_was = @capo
28
+ set_capo(capo)
29
+ yield
30
+ ensure
31
+ set_capo(capo_was)
32
+ end
33
+
26
34
  def fingers
27
35
  @strings.map { |string| string.dead? ? DEAD : string.fret }
28
36
  end
@@ -48,6 +48,13 @@ module WTFChord
48
48
  dead? ? -1 : to_i
49
49
  end
50
50
 
51
+ def distance_to(pitch)
52
+ pos = 0
53
+ opened = dup.open
54
+ pos += 1 while (opened + pos) != pitch
55
+ pos
56
+ end
57
+
51
58
  def <=> other
52
59
  return if dead?
53
60
  case other
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WTFChord
4
+ module RomanNumbersHelper
5
+ ROMAN_SYMBOLS ||= ("\u2160".."\u216B").to_a.unshift(nil).freeze
6
+
7
+ def romanize(number)
8
+ ROMAN_SYMBOLS[number]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WTFChord
4
+ class Keyboard
5
+ FRAME = <<~EOF
6
+ ┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
7
+ │ │ ││ │ │ │ ││ ││ │ │
8
+ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
9
+ │ │ │ │ │ │ │ │
10
+ └──┴──┴──┴──┴──┴──┴──┘
11
+ EOF
12
+
13
+ Key = Struct.new(:offset)
14
+ class Key
15
+ singleton_class.attr_accessor :select_symbol
16
+ singleton_class.alias_method :[], :new
17
+
18
+ def select(frame)
19
+ frame[offset] = self.class.select_symbol
20
+ frame
21
+ end
22
+ end
23
+
24
+ W = Class.new(Key) { self.select_symbol = "▐▌" }
25
+ B = Class.new(Key) { self.select_symbol = "█" }
26
+
27
+ KEYS = {
28
+ 1 => W[70...72],
29
+ 2 => B[26...27],
30
+ 3 => W[73...75],
31
+ 4 => B[29...30],
32
+ 5 => W[76...78],
33
+ 6 => W[79...81],
34
+ 7 => B[35...36],
35
+ 8 => W[82...84],
36
+ 9 => B[38...39],
37
+ 10 => W[85...87],
38
+ 11 => B[41...42],
39
+ 12 => W[88...90]
40
+ }
41
+
42
+ def self.press(*positions)
43
+ positions.each_with_object(FRAME.dup) do |pos, frame|
44
+ KEYS.fetch(pos).select(frame)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -25,8 +25,9 @@ module WTFChord
25
25
 
26
26
  def == other
27
27
  case other
28
- when String then other.casecmp(@key).zero?
29
- when Integer, Note then other == @position
28
+ when String then other.casecmp(@key).zero? || aliases.any? { |a| other.casecmp(a.key).zero? }
29
+ when Integer then other == @position
30
+ when Note then other.position == @position
30
31
  end
31
32
  end
32
33
 
@@ -46,6 +46,10 @@ module WTFChord
46
46
  move -amount
47
47
  end
48
48
 
49
+ def -@
50
+ -to_i
51
+ end
52
+
49
53
  def to_i
50
54
  (@octave * 12) + @note.position
51
55
  end
@@ -23,7 +23,9 @@ module WTFChord
23
23
  name.match(pattern) do |m|
24
24
  base = chords[m[:name]] || chords["M"]
25
25
  steps.concat(base)
26
- steps.concat(extra[m[:ext]]) if m[:ext] && m[:ext].length <= (6 - steps.length)
26
+
27
+ ext = extra[m[:ext]] if m[:ext]
28
+ steps.concat(ext) if ext
27
29
  end
28
30
 
29
31
  steps.tap(&:uniq!)
@@ -63,5 +63,11 @@ module WTFChord
63
63
  ScaleArray.build(*chromatic_scale).freeze
64
64
  end
65
65
 
66
- GUITAR ||= Fretboard.new(*%w(E2 A2 D3 G3 B3 E4))
66
+ def self.guitar=(guitar)
67
+ Thread.current[:wtf_guitar] = guitar
68
+ end
69
+
70
+ def self.guitar
71
+ Thread.current[:wtf_guitar] ||= Fretboard.new(*%w(E2 A2 D3 G3 B3 E4))
72
+ end
67
73
  end
@@ -1,3 +1,3 @@
1
1
  module WTFChord
2
- VERSION = "0.2.1"
2
+ VERSION = "0.6.0"
3
3
  end
data/wtf_chord.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_runtime_dependency "methadone"
24
24
 
25
- spec.add_development_dependency "bundler", ">= 1.11", "< 2"
26
- spec.add_development_dependency "rake", ">= 10.0", "< 12"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rake"
27
27
  spec.add_development_dependency "rspec", ">= 3.0", "< 4"
28
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wtf_chord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-03 00:00:00.000000000 Z
11
+ date: 2021-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: methadone
@@ -30,40 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.11'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '2'
33
+ version: '0'
37
34
  type: :development
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
- version: '1.11'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '2'
40
+ version: '0'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: rake
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
45
  - - ">="
52
46
  - !ruby/object:Gem::Version
53
- version: '10.0'
54
- - - "<"
55
- - !ruby/object:Gem::Version
56
- version: '12'
47
+ version: '0'
57
48
  type: :development
58
49
  prerelease: false
59
50
  version_requirements: !ruby/object:Gem::Requirement
60
51
  requirements:
61
52
  - - ">="
62
53
  - !ruby/object:Gem::Version
63
- version: '10.0'
64
- - - "<"
65
- - !ruby/object:Gem::Version
66
- version: '12'
54
+ version: '0'
67
55
  - !ruby/object:Gem::Dependency
68
56
  name: rspec
69
57
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +83,7 @@ files:
95
83
  - ".gitignore"
96
84
  - ".rspec"
97
85
  - ".travis.yml"
86
+ - CHANGELOG.md
98
87
  - Gemfile
99
88
  - README.md
100
89
  - Rakefile
@@ -107,12 +96,16 @@ files:
107
96
  - lib/wtf_chord/cli.rb
108
97
  - lib/wtf_chord/complexity_counter.rb
109
98
  - lib/wtf_chord/fingering.rb
99
+ - lib/wtf_chord/fingerings_generator.rb
110
100
  - lib/wtf_chord/formatter.rb
111
101
  - lib/wtf_chord/formatters/base.rb
112
102
  - lib/wtf_chord/formatters/default.rb
103
+ - lib/wtf_chord/formatters/piano.rb
113
104
  - lib/wtf_chord/formatters/simple.rb
114
105
  - lib/wtf_chord/fretboard.rb
115
106
  - lib/wtf_chord/guitar_string.rb
107
+ - lib/wtf_chord/helpers/roman_numbers_helper.rb
108
+ - lib/wtf_chord/keyboard.rb
116
109
  - lib/wtf_chord/note.rb
117
110
  - lib/wtf_chord/pitch.rb
118
111
  - lib/wtf_chord/rules.rb
@@ -137,10 +130,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
130
  - !ruby/object:Gem::Version
138
131
  version: '0'
139
132
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.5.1
133
+ rubygems_version: 3.0.3
142
134
  signing_key:
143
135
  specification_version: 4
144
136
  summary: "‘WTF Chord?’ is the Ruby guitar chords generator library."
145
137
  test_files: []
146
- has_rdoc: