wtf_chord 0.2.1 → 0.3

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
2
  SHA1:
3
- metadata.gz: 23feadfbf5375e890423135cc86a56d9b70af3e8
4
- data.tar.gz: aaa6a0d46fbeb51e715306da3d127b86816ed293
3
+ metadata.gz: 0ffe99b5205f9a4cbde1ebdd815a41dc9f8f0836
4
+ data.tar.gz: d08a21cf109465b729d171e88e7a3f3631ca95df
5
5
  SHA512:
6
- metadata.gz: 711ef213b9ea7302e812c122fda26aee2bb305960a0a1fc3f687106948ea401dcfe17eaeac3972d9a42f6bdf22f6189d01255be790bf89194dbb5e6479a3d86c
7
- data.tar.gz: 4c081a0a57e196422c13fa0a40f671e55d2b39ad49f96678c8b87da277d5e242d4d38fd19924d7e0d920444cc290af7d5984208e75f8a1cbc4dbeeddd10e7547
6
+ metadata.gz: e250bfa2ee065d20208dfca8831b33c216b2a4c2c450fecae75bef2a9b8c69189c2d6fd244dff31c25c00c38f9549d579f42b7ba6fca557509fb5a88460a2290
7
+ data.tar.gz: 25a18c48cecc08247ccfa78c6c396d2edd9c4481b0c86f39cf23636fb1b7bf51ba038d15b5e2fd0db8cd89c904aaf5d939cacb1a78233dcd0e7108495e1fd4cc
@@ -1,10 +1,8 @@
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
7
-
8
6
  attr_reader :pitch, :steps, :notes, :name
9
7
 
10
8
  def initialize(note, name)
@@ -18,51 +16,13 @@ module WTFChord
18
16
  "#{name} (#{@notes.map(&:key) * ' - '})"
19
17
  end
20
18
 
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)
28
- end
29
-
30
- sort_fingerings(list, limit)
31
- end
32
-
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
43
- end
44
-
45
- def all_notes?(strings)
46
- snotes = strings.map(&:note).tap(&:uniq!)
47
- @notes.all? { |n| snotes.include?(n) }
48
- end
49
-
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]
57
- end
58
-
59
- def should_adjust?(string, i = 0)
60
- string && string.note != @notes[i]
19
+ def fingerings(limit = nil)
20
+ limit ||= 5
21
+ FingeringsGenerator.new(self).call[0, limit]
61
22
  end
62
23
 
63
- def sort_fingerings(list, limit)
64
- list.sort_by!(&:complexity)
65
- list[0...limit].sort_by!(&:min_fret)
24
+ def third_tone
25
+ @third_tone ||= @notes[@steps.index(7) || -1]
66
26
  end
67
27
  end
68
28
  end
data/lib/wtf_chord/cli.rb CHANGED
@@ -31,7 +31,7 @@ module WTFChord
31
31
  ##
32
32
  # Options
33
33
  #
34
- options['amount'] = 3
34
+ options['amount'] = 5
35
35
  options['output'] = 'default'
36
36
  options['rates'] = false
37
37
 
@@ -6,17 +6,27 @@ 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
31
  base_rate
22
32
  end
@@ -4,9 +4,10 @@ require 'wtf_chord/formatter'
4
4
 
5
5
  module WTFChord
6
6
  class Fingering < Fretboard
7
- def initialize(guitar)
7
+ def initialize(guitar, fingers = nil)
8
8
  @capo = guitar.capo
9
9
  @strings = guitar.strings.map(&:dup)
10
+ set_fingers(fingers) if fingers.is_a?(Array)
10
11
  yield(self) if block_given?
11
12
  end
12
13
 
@@ -0,0 +1,85 @@
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 << variant if filter_variant(variant)
20
+ end
21
+ end
22
+
23
+ fingerings.sort_by!(&:complexity)
24
+ end
25
+
26
+ private
27
+
28
+ def generate(fret_range)
29
+ combinations = GUITAR.strings.map.with_index do |s, index|
30
+ fret_range.select do |dist|
31
+ pitch = s.original + dist
32
+ has_note?(pitch)
33
+ end.tap do |frets|
34
+ frets << nil if frets.size == 0
35
+ end
36
+ end
37
+
38
+ combinations.inject(&:product).each do |fingers|
39
+ fingers.flatten!
40
+ Fingering.new(GUITAR, fingers) do |variant|
41
+ adjust(variant)
42
+ yield(variant)
43
+ end
44
+ end
45
+ end
46
+
47
+ def filter_variant(variant)
48
+ used_strings = variant.used_strings
49
+ used_notes = used_strings.map(&:note)
50
+ tones_count = notes.map { |n| used_notes.count(n) }
51
+
52
+ !fingerings.include?(variant) &&
53
+ basetone?(used_strings[0]) &&
54
+ (third?(used_strings[1]) || third?(used_strings[2])) &&
55
+ all_notes?(used_notes) &&
56
+ used_notes.each_cons(2).none? { |(l, r)| l == r } &&
57
+ tones_count.all? { |n| tones_count[0] >= n || tones_count[notes.index(third_tone)] >= n } &&
58
+ variant.complexity <= 2.25
59
+ end
60
+
61
+ def adjust(fingering)
62
+ while (string = fingering.used_strings[0]) && !basetone?(string)
63
+ string.dead if !string.dead?
64
+ break if fingering.used_strings.size == 4
65
+ end
66
+ end
67
+
68
+ def all_notes?(used_notes)
69
+ notes.all? { |n| used_notes.include?(n) }
70
+ end
71
+
72
+ def has_note?(value)
73
+ value = value.note if !value.is_a?(Note) && value.respond_to?(:note)
74
+ notes.include?(value)
75
+ end
76
+
77
+ def basetone?(string)
78
+ string && string.note == notes[0]
79
+ end
80
+
81
+ def third?(string)
82
+ string && (string.note == third_tone)
83
+ end
84
+ end
85
+ 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?
29
+ when Integer then other == @position
30
+ when Note then other.position == @position
30
31
  end
31
32
  end
32
33
 
@@ -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!)
@@ -1,3 +1,3 @@
1
1
  module WTFChord
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
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.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton
@@ -107,6 +107,7 @@ files:
107
107
  - lib/wtf_chord/cli.rb
108
108
  - lib/wtf_chord/complexity_counter.rb
109
109
  - lib/wtf_chord/fingering.rb
110
+ - lib/wtf_chord/fingerings_generator.rb
110
111
  - lib/wtf_chord/formatter.rb
111
112
  - lib/wtf_chord/formatters/base.rb
112
113
  - lib/wtf_chord/formatters/default.rb