From c11be84d6acb665ff9a6bff3c91193bb010aa813 Mon Sep 17 00:00:00 2001 From: Nalin Bhardwaj Date: Wed, 16 Aug 2017 04:10:48 +0530 Subject: [PATCH] Music Chords Diagrams: Fixes/improves triggering (#4085) * Fixes regex to correctly find values * Adding multiple naming to instruments * Fixes #3386 * Adds more sharp/flat aliases for ukulele * Remove debug print * Multiple whitespace matching * Adding support for tabs, chords * Adding tests --- lib/DDG/Goodie/ChordDiagrams.pm | 28 +++++++---------- share/goodie/chord_diagrams/ukulele.json | 8 ++--- t/ChordDiagrams.t | 38 +++++++++++++++++++++++- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/lib/DDG/Goodie/ChordDiagrams.pm b/lib/DDG/Goodie/ChordDiagrams.pm index 64448ff78..69d8774d6 100644 --- a/lib/DDG/Goodie/ChordDiagrams.pm +++ b/lib/DDG/Goodie/ChordDiagrams.pm @@ -10,7 +10,7 @@ use List::Util qw(min); zci answer_type => "chord_diagrams"; zci is_cached => 1; -triggers any => "chord", "tab"; +triggers any => "chord", "tab", "chords", "tabs"; # Store the instruments that the program will respond to, with a # list storing the note of each string in order. (Add one to note @@ -18,11 +18,13 @@ triggers any => "chord", "tab"; my %instruments = ( guitar => { chords => decode_json(share('guitar.json')->slurp), - strings => 6 + strings => 6, + names => 'guitar' }, ukulele => { chords => decode_json(share('ukulele.json')->slurp), - strings => 4 + strings => 4, + names => 'ukulele|uke' } ); @@ -142,7 +144,7 @@ sub gen_svg { # used in items -my %mod_hash = (sharp => 1, b => -1); +my %mod_hash = (sharp => '#', b => 'b'); # The input parser. Uses regex to find the key to put the chord in, and the # chord if they are conjoined. @@ -151,12 +153,12 @@ my %mod_hash = (sharp => 1, b => -1); sub items { my @words = split(" ", lc $_[0]); $_[0] = join("sharp", split("#", $_[0])); - my ($temp, $key, $mod, $chord, $dom, $temp2) = /( |^)([a-g])(sharp|b|)(m|min|minor|M|maj|major|sus[24]|aug9?|)(5|7|9|11|13|)( |$)/i ; + my ($temp, $key, $mod, $chord, $dom, $temp2) = /( |^)(?:\s)*([a-g])(?:\s)*(sharp|b|)(?:\s)*(m|min|minor|M|maj|major|sus[24]|aug9?|)(?:\s)*(5|7|9|11|13|)(?:\s)*( |$)/i; if(/( |^)(5|7|9)( |$)/i) { ($temp, $dom, $temp2) = /( |^)(5|7|9|11|13)( |$)/i; } if(/( |^)(5|7|9)th( |$)/i) { ($temp, $dom, $temp2) = /( |^)(5|7|9|11|13)th( |$)/i; } - $mod = $mod ? ($mod_hash{$mod} || 0) : 0; + $mod = $mod ? ($mod_hash{$mod} || '') : ''; $key ||= ""; $dom ||= ""; $chord ||= ""; @@ -171,11 +173,12 @@ sub items { my $instr; foreach my $i (keys %instruments) { - if(grep(/^$i$/, @words)) { + if(grep(/^$instruments{$i}{"names"}$/, @words)) { $instr = $i; last; } } + return $instr, $chord, uc $key, $mod, $dom; }; @@ -198,22 +201,13 @@ sub get_chord { return; }; -# turn a mod number into a symbol -sub mod_sign { - return "b" if $_ eq -1; - return "#" if $_ eq 1; - return ""; -}; - # Handle statement handle remainder => sub { my ($instr_name, $chord_name, $key_name, $mod, $dom) = items($_); return unless $instr_name && $chord_name && $key_name; my $strings = $instruments{$instr_name}{"strings"}; my $length = 4; - $mod = mod_sign $mod; - my $input = join(" ", (uc $key_name) . $mod, $chord_name . $dom, "guitar chord"); - + return unless my $r = get_chord($key_name . $mod, $chord_name . $dom, $instruments{$instr_name}{"chords"}); my @results = @{$r}; diff --git a/share/goodie/chord_diagrams/ukulele.json b/share/goodie/chord_diagrams/ukulele.json index aa5cf99b1..cdcbb1635 100644 --- a/share/goodie/chord_diagrams/ukulele.json +++ b/share/goodie/chord_diagrams/ukulele.json @@ -238,7 +238,7 @@ [ 0, 0, 1, 3 ] ] }]}, { -"root": ["C#"], +"root": ["C#", "Db"], "types": [{ "name": "maj", "variations": [ @@ -345,7 +345,7 @@ [ 2, 2, 3, 0 ] ] }]}, { -"root": ["D#"], +"root": ["D#", "Eb"], "types": [{ "name": "maj", "variations": [ @@ -507,7 +507,7 @@ [ 3, 0, 1, 3 ] ] }]}, { -"root": ["F#"], +"root": ["F#", "Gb"], "types": [{ "name": "maj", "variations": [ @@ -615,7 +615,7 @@ [ 0, 2, 3, 3 ] ] }]}, { -"root": ["G#"], +"root": ["G#", "Ab"], "types": [{ "name": "maj", "variations": [ diff --git a/t/ChordDiagrams.t b/t/ChordDiagrams.t index 1b938c78c..08ed6ab9e 100644 --- a/t/ChordDiagrams.t +++ b/t/ChordDiagrams.t @@ -46,13 +46,49 @@ structured_answer => { } }, }), +'Eb uke tabs' => test_zci( +'chord_diagrams', +structured_answer => { + id => 'chord_diagrams', + name => 'Music', + data => re(qr/.*/), + templates => { + group => "base", + detail => 0, + options => { + content => 'DDH.chord_diagrams.detail' + }, + variants => { + tile => 'narrow' + } + }, +}), +'A major guitar tab' => test_zci( +'chord_diagrams', +structured_answer => { + id => 'chord_diagrams', + name => 'Music', + data => re(qr/.*/), + templates => { + group => "base", + detail => 0, + options => { + content => 'DDH.chord_diagrams.detail' + }, + variants => { + tile => 'narrow' + } + }, +}), # check that certain things don't trigger it: 'C# programming' => undef, 'C programming' => undef, 'D programming' => undef, 'guitar chord finder' => undef, 'guitar chord fminute' => undef, -'G' => undef +'G' => undef, +'A sharp tabs' => undef, +'randomstring guitar chords' => undef ); done_testing;