ruby_speech 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/CHANGELOG.md +6 -0
- data/Guardfile +1 -1
- data/ext/ruby_speech/RubySpeechGRXMLMatcher.java +30 -8
- data/ext/ruby_speech/ruby_speech.c +72 -16
- data/lib/ruby_speech/generic_element.rb +4 -7
- data/lib/ruby_speech/grxml/grammar.rb +1 -1
- data/lib/ruby_speech/grxml/match.rb +1 -1
- data/lib/ruby_speech/grxml/matcher.rb +14 -24
- data/lib/ruby_speech/grxml/max_match.rb +6 -0
- data/lib/ruby_speech/grxml.rb +1 -0
- data/lib/ruby_speech/version.rb +1 -1
- data/ruby_speech.gemspec +1 -1
- data/spec/ruby_speech/grxml/match_spec.rb +3 -37
- data/spec/ruby_speech/grxml/matcher_spec.rb +52 -43
- data/spec/ruby_speech/grxml/max_match_spec.rb +17 -0
- data/spec/support/match_examples.rb +43 -0
- data/spec/support/matchers.rb +1 -7
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de37299d09f7a9dc63c8c5944db79f80594bfffc
|
4
|
+
data.tar.gz: c01558ff39e76c034f1b18df7288c27d04ec84b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2dc9ae2659cc93d40f7f0d55a2d6b4344accf12f7b1d7cf130aba09c4949a868bc47e2c641183aecad8bd42b0312a50d3a14d27eb9b933664fbaaa15de60cdc
|
7
|
+
data.tar.gz: 3df44bf14ab55473bd2dab097e2e972493744d299390085506e90ff437eb82441f535a3b29b1a45ac73d22c1770d0f4e4de9dbbb954d3d3c7c6983f12a741b75
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# [develop](https://github.com/benlangfeld/ruby_speech)
|
2
2
|
|
3
|
+
# [2.0.2](https://github.com/benlangfeld/ruby_speech/compare/v2.0.1...v2.0.2) - [2013-05-01](https://rubygems.org/gems/ruby_speech/versions/2.0.2)
|
4
|
+
* Bugfix: Differentiate between GRXML match cases with are and are not maximal
|
5
|
+
* A Match can accept further input while still matching, while a a MaxMatch cannot.
|
6
|
+
* Matching implementation moved down to C/Java to avoid repeated regex compilation and confusing jumping about.
|
7
|
+
* Bugfix: Back to functioning on JRuby with latest Nokogiri release
|
8
|
+
|
3
9
|
# [2.0.1](https://github.com/benlangfeld/ruby_speech/compare/v2.0.0...v2.0.1) - [2013-04-27](https://rubygems.org/gems/ruby_speech/versions/2.0.1)
|
4
10
|
* Bugfix: Build native C extension in the correct location
|
5
11
|
|
data/Guardfile
CHANGED
@@ -17,26 +17,48 @@ import java.util.regex.*;
|
|
17
17
|
@JRubyClass(name="RubySpeech::GRXML::Matcher")
|
18
18
|
public class RubySpeechGRXMLMatcher extends RubyObject {
|
19
19
|
|
20
|
+
Pattern p;
|
21
|
+
|
20
22
|
public RubySpeechGRXMLMatcher(final Ruby runtime, RubyClass rubyClass) {
|
21
23
|
super(runtime, rubyClass);
|
22
24
|
}
|
23
25
|
|
24
26
|
@JRubyMethod(visibility=Visibility.PRIVATE)
|
25
|
-
public IRubyObject
|
26
|
-
{
|
27
|
+
public IRubyObject compile_regex(ThreadContext context, IRubyObject regex) {
|
27
28
|
Ruby runtime = context.getRuntime();
|
29
|
+
p = Pattern.compile(regex.toString());
|
30
|
+
return runtime.getNil();
|
31
|
+
}
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
@JRubyMethod(visibility=Visibility.PUBLIC)
|
34
|
+
public IRubyObject find_match(ThreadContext context, IRubyObject buffer)
|
35
|
+
{
|
36
|
+
Ruby runtime = context.getRuntime();
|
37
|
+
String string_buffer = buffer.toString();
|
38
|
+
Matcher m = p.matcher(string_buffer);
|
33
39
|
|
34
40
|
if (m.matches()) {
|
41
|
+
if (is_max_match(string_buffer)) {
|
42
|
+
return RuntimeHelpers.invoke(context, this, "match_for_buffer", buffer, runtime.getTrue());
|
43
|
+
}
|
44
|
+
return callMethod(context, "match_for_buffer", buffer);
|
35
45
|
} else if (m.hitEnd()) {
|
36
46
|
RubyModule potential_match = runtime.getClassFromPath("RubySpeech::GRXML::PotentialMatch");
|
37
|
-
return
|
47
|
+
return potential_match.callMethod(context, "new");
|
38
48
|
}
|
39
|
-
|
49
|
+
RubyModule nomatch = runtime.getClassFromPath("RubySpeech::GRXML::NoMatch");
|
50
|
+
return nomatch.callMethod(context, "new");
|
51
|
+
}
|
52
|
+
|
53
|
+
public Boolean is_max_match(String buffer)
|
54
|
+
{
|
55
|
+
String search_set = "0123456789#*ABCD";
|
56
|
+
for (int i = 0; i < 16; i++) {
|
57
|
+
String new_buffer = buffer + search_set.charAt(i);
|
58
|
+
Matcher m = p.matcher(new_buffer);
|
59
|
+
if (m.matches()) return false;
|
60
|
+
}
|
61
|
+
return true;
|
40
62
|
}
|
41
63
|
|
42
64
|
}
|
@@ -2,33 +2,88 @@
|
|
2
2
|
#include "pcre.h"
|
3
3
|
#include <stdio.h>
|
4
4
|
|
5
|
-
static VALUE
|
5
|
+
static VALUE method_compile_regex(VALUE self, VALUE regex_string)
|
6
6
|
{
|
7
|
-
int erroffset
|
8
|
-
const char *errptr
|
9
|
-
int options
|
10
|
-
|
11
|
-
const char *regex = StringValueCStr(regex_string);
|
7
|
+
int erroffset = 0;
|
8
|
+
const char *errptr = "";
|
9
|
+
int options = 0;
|
10
|
+
const char *regex = StringValueCStr(regex_string);
|
12
11
|
|
13
12
|
pcre *compiled_regex = pcre_compile(regex, options, &errptr, &erroffset, NULL);
|
13
|
+
VALUE compiled_regex_wrapper = Data_Wrap_Struct(rb_cObject, 0, pcre_free, compiled_regex);
|
14
|
+
rb_iv_set(self, "@regex", compiled_regex_wrapper);
|
14
15
|
|
16
|
+
return Qnil;
|
17
|
+
}
|
18
|
+
|
19
|
+
#define MAX_INPUT_SIZE 128
|
20
|
+
#define OVECTOR_SIZE 30
|
21
|
+
#define WORKSPACE_SIZE 1024
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Check if no more digits can be added to input and match
|
25
|
+
* @param compiled_regex the regex used in the initial match
|
26
|
+
* @param input the input to check
|
27
|
+
* @return true if end of match (no more input can be added)
|
28
|
+
*/
|
29
|
+
static int is_match_end(pcre *compiled_regex, const char *input)
|
30
|
+
{
|
31
|
+
int ovector[OVECTOR_SIZE];
|
32
|
+
int input_size = (int)strlen(input);
|
33
|
+
char search_input[MAX_INPUT_SIZE + 2];
|
34
|
+
const char *search_set = "0123456789#*ABCD";
|
35
|
+
const char *search = strchr(search_set, input[input_size - 1]); /* start with last digit in input */
|
36
|
+
|
37
|
+
/* For each digit in search_set, check if input + search_set digit is a potential match.
|
38
|
+
If so, then this is not a match end.
|
39
|
+
*/
|
40
|
+
sprintf(search_input, "%sZ", input);
|
41
|
+
int i;
|
42
|
+
for (i = 0; i < 16; i++) {
|
43
|
+
int result;
|
44
|
+
if (!*search) {
|
45
|
+
search = search_set;
|
46
|
+
}
|
47
|
+
search_input[input_size] = *search++;
|
48
|
+
result = pcre_exec(compiled_regex, NULL, search_input, input_size + 1, 0, 0,
|
49
|
+
ovector, sizeof(ovector) / sizeof(ovector[0]));
|
50
|
+
if (result > 0) return 0;
|
51
|
+
}
|
52
|
+
return 1;
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE method_find_match(VALUE self, VALUE buffer)
|
56
|
+
{
|
57
|
+
VALUE RubySpeech = rb_const_get(rb_cObject, rb_intern("RubySpeech"));
|
58
|
+
VALUE GRXML = rb_const_get(RubySpeech, rb_intern("GRXML"));
|
59
|
+
VALUE NoMatch = rb_const_get(GRXML, rb_intern("NoMatch"));
|
60
|
+
pcre *compiled_regex;
|
15
61
|
int result = 0;
|
16
|
-
int ovector[
|
17
|
-
int workspace[
|
62
|
+
int ovector[OVECTOR_SIZE];
|
63
|
+
int workspace[WORKSPACE_SIZE];
|
18
64
|
char *input = StringValueCStr(buffer);
|
19
|
-
|
65
|
+
|
66
|
+
Data_Get_Struct(rb_iv_get(self, "@regex"), pcre, compiled_regex);
|
67
|
+
|
68
|
+
if (!compiled_regex) {
|
69
|
+
return rb_class_new_instance(0, NULL, NoMatch);
|
70
|
+
}
|
71
|
+
|
72
|
+
result = pcre_dfa_exec(compiled_regex, NULL, input, (int)strlen(input), 0, PCRE_PARTIAL,
|
20
73
|
ovector, sizeof(ovector) / sizeof(ovector[0]),
|
21
74
|
workspace, sizeof(workspace) / sizeof(workspace[0]));
|
22
|
-
pcre_free(compiled_regex);
|
23
75
|
|
76
|
+
if (result > 0) {
|
77
|
+
if (is_match_end(compiled_regex, input)) {
|
78
|
+
return rb_funcall(self, rb_intern("match_for_buffer"), 2, buffer, Qtrue);
|
79
|
+
}
|
80
|
+
return rb_funcall(self, rb_intern("match_for_buffer"), 1, buffer);
|
81
|
+
}
|
24
82
|
if (result == PCRE_ERROR_PARTIAL) {
|
25
|
-
VALUE
|
26
|
-
VALUE GRXML = rb_const_get(RubySpeech, rb_intern("GRXML"));
|
27
|
-
VALUE PotentialMatch = rb_const_get(GRXML, rb_intern("PotentialMatch"));
|
28
|
-
|
83
|
+
VALUE PotentialMatch = rb_const_get(GRXML, rb_intern("PotentialMatch"));
|
29
84
|
return rb_class_new_instance(0, NULL, PotentialMatch);
|
30
85
|
}
|
31
|
-
return
|
86
|
+
return rb_class_new_instance(0, NULL, NoMatch);
|
32
87
|
}
|
33
88
|
|
34
89
|
void Init_ruby_speech()
|
@@ -37,5 +92,6 @@ void Init_ruby_speech()
|
|
37
92
|
VALUE GRXML = rb_define_module_under(RubySpeech, "GRXML");
|
38
93
|
VALUE Matcher = rb_define_class_under(GRXML, "Matcher", rb_cObject);
|
39
94
|
|
40
|
-
rb_define_method(Matcher, "
|
95
|
+
rb_define_method(Matcher, "find_match", method_find_match, 1);
|
96
|
+
rb_define_method(Matcher, "compile_regex", method_compile_regex, 1);
|
41
97
|
}
|
@@ -109,17 +109,14 @@ module RubySpeech
|
|
109
109
|
|
110
110
|
def children(type = nil, attributes = nil)
|
111
111
|
if type
|
112
|
-
expression =
|
112
|
+
expression = namespace_href ? 'ns:' : ''
|
113
|
+
expression << type.to_s
|
113
114
|
|
114
115
|
expression << '[' << attributes.inject([]) do |h, (key, value)|
|
115
|
-
h << "@#{key}='#{value}'"
|
116
|
+
h << "@#{namespace_href && Nokogiri.jruby? ? 'ns:' : ''}#{key}='#{value}'"
|
116
117
|
end.join(',') << ']' if attributes
|
117
118
|
|
118
|
-
|
119
|
-
xpath "ns:#{expression}", :ns => namespace_href
|
120
|
-
else
|
121
|
-
xpath expression
|
122
|
-
end
|
119
|
+
xpath expression, :ns => namespace_href
|
123
120
|
else
|
124
121
|
super()
|
125
122
|
end.map { |c| self.class.import c }
|
@@ -109,7 +109,7 @@ module RubySpeech
|
|
109
109
|
ref.swap rule.nokogiri_children
|
110
110
|
end
|
111
111
|
|
112
|
-
non_root_rules = xpath "./ns:rule[
|
112
|
+
non_root_rules = xpath "./ns:rule[@#{namespace_href && Nokogiri.jruby? ? 'ns:' : ''}id!='#{root}']", :ns => namespace_href
|
113
113
|
non_root_rules.remove
|
114
114
|
|
115
115
|
self
|
@@ -8,7 +8,7 @@ module RubySpeech
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def eql?(o)
|
11
|
-
o.
|
11
|
+
o.instance_of?(self.class) && [:mode, :confidence, :utterance, :interpretation].all? { |f| self.__send__(f) == o.__send__(f) }
|
12
12
|
end
|
13
13
|
alias :== :eql?
|
14
14
|
end
|
@@ -8,15 +8,12 @@ end
|
|
8
8
|
module RubySpeech
|
9
9
|
module GRXML
|
10
10
|
class Matcher
|
11
|
-
|
12
|
-
BLANK_REGEX = //.freeze
|
13
|
-
|
14
|
-
attr_reader :grammar, :regex
|
11
|
+
attr_reader :grammar
|
15
12
|
|
16
13
|
def initialize(grammar)
|
17
14
|
@grammar = grammar
|
18
15
|
prepare_grammar
|
19
|
-
|
16
|
+
compile_regex regexp_content
|
20
17
|
end
|
21
18
|
|
22
19
|
##
|
@@ -24,7 +21,7 @@ module RubySpeech
|
|
24
21
|
#
|
25
22
|
# @param [String] other the input string to check for a match with the grammar
|
26
23
|
#
|
27
|
-
# @return [NoMatch, Match] depending on the result of a match attempt. If a match can be found, it will be returned with appropriate mode/confidence/utterance and interpretation attributes
|
24
|
+
# @return [NoMatch, PotentialMatch, Match, MaxMatch] depending on the result of a match attempt. A potential match indicates that the buffer is valid, but incomplete. A MaxMatch is differentiated from a Match in that it cannot accept further input. If a match can be found, it will be returned with appropriate mode/confidence/utterance and interpretation attributes
|
28
25
|
#
|
29
26
|
# @example A grammar that takes a 4 digit pin terminated by hash, or the *9 escape sequence
|
30
27
|
# ```ruby
|
@@ -85,34 +82,27 @@ module RubySpeech
|
|
85
82
|
# ```
|
86
83
|
#
|
87
84
|
def match(buffer)
|
88
|
-
|
89
|
-
|
90
|
-
return check_potential_match(buffer) if regex == BLANK_REGEX
|
91
|
-
|
92
|
-
check_full_match(buffer) || check_potential_match(buffer) || NoMatch.new
|
85
|
+
find_match buffer.dup
|
93
86
|
end
|
94
87
|
|
95
88
|
private
|
96
89
|
|
90
|
+
def regexp_content
|
91
|
+
'^' + grammar.root_rule.children.map(&:regexp_content).join + '$'
|
92
|
+
end
|
93
|
+
|
97
94
|
def prepare_grammar
|
98
95
|
grammar.inline!
|
99
96
|
grammar.tokenize!
|
100
97
|
grammar.normalize_whitespace
|
101
98
|
end
|
102
99
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
:confidence => grammar.dtmf? ? 1 : 0,
|
110
|
-
:utterance => buffer,
|
111
|
-
:interpretation => interpret_utterance(buffer)
|
112
|
-
end
|
113
|
-
|
114
|
-
def regexp_content
|
115
|
-
grammar.root_rule.children.map &:regexp_content
|
100
|
+
def match_for_buffer(buffer, maximal = false)
|
101
|
+
match_class = maximal ? MaxMatch : Match
|
102
|
+
match_class.new mode: grammar.mode,
|
103
|
+
confidence: grammar.dtmf? ? 1 : 0,
|
104
|
+
utterance: buffer,
|
105
|
+
interpretation: interpret_utterance(buffer)
|
116
106
|
end
|
117
107
|
|
118
108
|
def interpret_utterance(utterance)
|
data/lib/ruby_speech/grxml.rb
CHANGED
data/lib/ruby_speech/version.rb
CHANGED
data/ruby_speech.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.extensions = ['ext/ruby_speech/extconf.rb']
|
26
26
|
end
|
27
27
|
|
28
|
-
s.add_runtime_dependency %q<niceogiri>, ["~> 1.1", ">= 1.1.
|
28
|
+
s.add_runtime_dependency %q<niceogiri>, ["~> 1.1", ">= 1.1.2"]
|
29
29
|
s.add_runtime_dependency %q<nokogiri>, ["~> 1.5", ">= 1.5.6"]
|
30
30
|
s.add_runtime_dependency %q<activesupport>, [">= 3.0.7"]
|
31
31
|
|
@@ -3,45 +3,11 @@ require 'spec_helper'
|
|
3
3
|
module RubySpeech
|
4
4
|
module GRXML
|
5
5
|
describe Match do
|
6
|
-
|
7
|
-
Match.new :mode => :dtmf,
|
8
|
-
:confidence => 1,
|
9
|
-
:utterance => '6',
|
10
|
-
:interpretation => 'foo'
|
11
|
-
end
|
12
|
-
|
13
|
-
its(:mode) { should == :dtmf }
|
14
|
-
its(:confidence) { should == 1 }
|
15
|
-
its(:utterance) { should == '6' }
|
16
|
-
its(:interpretation) { should == 'foo' }
|
6
|
+
it_behaves_like "match"
|
17
7
|
|
18
8
|
describe "equality" do
|
19
|
-
it "should be equal
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "when the mode is different" do
|
24
|
-
it "should not be equal" do
|
25
|
-
Match.new(:mode => :dtmf).should_not == Match.new(:mode => :speech)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "when the confidence is different" do
|
30
|
-
it "should not be equal" do
|
31
|
-
Match.new(:confidence => 1).should_not == Match.new(:confidence => 0)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "when the utterance is different" do
|
36
|
-
it "should not be equal" do
|
37
|
-
Match.new(:utterance => '6').should_not == Match.new(:utterance => 'foo')
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "when the interpretation is different" do
|
42
|
-
it "should not be equal" do
|
43
|
-
Match.new(:interpretation => 'foo').should_not == Match.new(:interpretation => 'bar')
|
44
|
-
end
|
9
|
+
it "should never be equal to a MaxMatch" do
|
10
|
+
described_class.new.should_not eql(MaxMatch.new)
|
45
11
|
end
|
46
12
|
end
|
47
13
|
end
|
@@ -17,9 +17,9 @@ module RubySpeech
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
it "should match '6'" do
|
20
|
+
it "should max-match '6'" do
|
21
21
|
input = '6'
|
22
|
-
expected_match = GRXML::
|
22
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
23
23
|
:confidence => 1,
|
24
24
|
:utterance => '6',
|
25
25
|
:interpretation => 'dtmf-6'
|
@@ -43,8 +43,8 @@ module RubySpeech
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
it "should match '56'" do
|
47
|
-
expected_match = GRXML::
|
46
|
+
it "should maximally match '56'" do
|
47
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
48
48
|
:confidence => 1,
|
49
49
|
:utterance => '56',
|
50
50
|
:interpretation => 'dtmf-5 dtmf-6'
|
@@ -73,8 +73,8 @@ module RubySpeech
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
it "should match '*6'" do
|
77
|
-
expected_match = GRXML::
|
76
|
+
it "should maximally match '*6'" do
|
77
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
78
78
|
:confidence => 1,
|
79
79
|
:utterance => '*6',
|
80
80
|
:interpretation => 'dtmf-star dtmf-6'
|
@@ -101,8 +101,8 @@ module RubySpeech
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
it "should match '#6'" do
|
105
|
-
expected_match = GRXML::
|
104
|
+
it "should maximally match '#6'" do
|
105
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
106
106
|
:confidence => 1,
|
107
107
|
:utterance => '#6',
|
108
108
|
:interpretation => 'dtmf-pound dtmf-6'
|
@@ -134,8 +134,8 @@ module RubySpeech
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
it "should match '*6'" do
|
138
|
-
expected_match = GRXML::
|
137
|
+
it "should maximally match '*6'" do
|
138
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
139
139
|
:confidence => 1,
|
140
140
|
:utterance => '*6',
|
141
141
|
:interpretation => 'dtmf-star dtmf-6'
|
@@ -165,16 +165,16 @@ module RubySpeech
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
it "should match '6'" do
|
169
|
-
expected_match = GRXML::
|
168
|
+
it "should maximally match '6'" do
|
169
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
170
170
|
:confidence => 1,
|
171
171
|
:utterance => '6',
|
172
172
|
:interpretation => 'dtmf-6'
|
173
173
|
subject.match('6').should == expected_match
|
174
174
|
end
|
175
175
|
|
176
|
-
it "should match '7'" do
|
177
|
-
expected_match = GRXML::
|
176
|
+
it "should maximally match '7'" do
|
177
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
178
178
|
:confidence => 1,
|
179
179
|
:utterance => '7',
|
180
180
|
:interpretation => 'dtmf-7'
|
@@ -206,16 +206,16 @@ module RubySpeech
|
|
206
206
|
end
|
207
207
|
end
|
208
208
|
|
209
|
-
it "should match '65'" do
|
210
|
-
expected_match = GRXML::
|
209
|
+
it "should maximally match '65'" do
|
210
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
211
211
|
:confidence => 1,
|
212
212
|
:utterance => '65',
|
213
213
|
:interpretation => 'dtmf-6 dtmf-5'
|
214
214
|
subject.match('65').should == expected_match
|
215
215
|
end
|
216
216
|
|
217
|
-
it "should match '72'" do
|
218
|
-
expected_match = GRXML::
|
217
|
+
it "should maximally match '72'" do
|
218
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
219
219
|
:confidence => 1,
|
220
220
|
:utterance => '72',
|
221
221
|
:interpretation => 'dtmf-7 dtmf-2'
|
@@ -255,16 +255,16 @@ module RubySpeech
|
|
255
255
|
end
|
256
256
|
end
|
257
257
|
|
258
|
-
it "should match '652'" do
|
259
|
-
expected_match = GRXML::
|
258
|
+
it "should maximally match '652'" do
|
259
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
260
260
|
:confidence => 1,
|
261
261
|
:utterance => '652',
|
262
262
|
:interpretation => 'dtmf-6 dtmf-5 dtmf-2'
|
263
263
|
subject.match('652').should == expected_match
|
264
264
|
end
|
265
265
|
|
266
|
-
it "should match '728'" do
|
267
|
-
expected_match = GRXML::
|
266
|
+
it "should maximally match '728'" do
|
267
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
268
268
|
:confidence => 1,
|
269
269
|
:utterance => '728',
|
270
270
|
:interpretation => 'dtmf-7 dtmf-2 dtmf-8'
|
@@ -297,16 +297,16 @@ module RubySpeech
|
|
297
297
|
end
|
298
298
|
end
|
299
299
|
|
300
|
-
it "should match '*6'" do
|
301
|
-
expected_match = GRXML::
|
300
|
+
it "should maximally match '*6'" do
|
301
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
302
302
|
:confidence => 1,
|
303
303
|
:utterance => '*6',
|
304
304
|
:interpretation => 'dtmf-star dtmf-6'
|
305
305
|
subject.match('*6').should == expected_match
|
306
306
|
end
|
307
307
|
|
308
|
-
it "should match '*7'" do
|
309
|
-
expected_match = GRXML::
|
308
|
+
it "should maximally match '*7'" do
|
309
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
310
310
|
:confidence => 1,
|
311
311
|
:utterance => '*7',
|
312
312
|
:interpretation => 'dtmf-star dtmf-7'
|
@@ -337,24 +337,26 @@ module RubySpeech
|
|
337
337
|
end
|
338
338
|
end
|
339
339
|
|
340
|
-
it "should match '6*'" do
|
341
|
-
expected_match = GRXML::
|
340
|
+
it "should maximally match '6*'" do
|
341
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
342
342
|
:confidence => 1,
|
343
343
|
:utterance => '6*',
|
344
344
|
:interpretation => 'dtmf-6 dtmf-star'
|
345
345
|
subject.match('6*').should == expected_match
|
346
346
|
end
|
347
347
|
|
348
|
-
it "should match '7*'" do
|
349
|
-
expected_match = GRXML::
|
348
|
+
it "should maximally match '7*'" do
|
349
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
350
350
|
:confidence => 1,
|
351
351
|
:utterance => '7*',
|
352
352
|
:interpretation => 'dtmf-7 dtmf-star'
|
353
353
|
subject.match('7*').should == expected_match
|
354
354
|
end
|
355
355
|
|
356
|
-
|
357
|
-
|
356
|
+
%w{6 7}.each do |input|
|
357
|
+
it "should potentially match '#{input}'" do
|
358
|
+
subject.match(input).should == GRXML::PotentialMatch.new
|
359
|
+
end
|
358
360
|
end
|
359
361
|
|
360
362
|
it "should potentially match '7'" do
|
@@ -380,8 +382,8 @@ module RubySpeech
|
|
380
382
|
end
|
381
383
|
end
|
382
384
|
|
383
|
-
it "should match '166'" do
|
384
|
-
expected_match = GRXML::
|
385
|
+
it "should maximally match '166'" do
|
386
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
385
387
|
:confidence => 1,
|
386
388
|
:utterance => '166',
|
387
389
|
:interpretation => 'dtmf-1 dtmf-6 dtmf-6'
|
@@ -413,8 +415,8 @@ module RubySpeech
|
|
413
415
|
end
|
414
416
|
end
|
415
417
|
|
416
|
-
it "should match '661'" do
|
417
|
-
expected_match = GRXML::
|
418
|
+
it "should maximally match '661'" do
|
419
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
418
420
|
:confidence => 1,
|
419
421
|
:utterance => '661',
|
420
422
|
:interpretation => 'dtmf-6 dtmf-6 dtmf-1'
|
@@ -446,11 +448,18 @@ module RubySpeech
|
|
446
448
|
end
|
447
449
|
end
|
448
450
|
|
451
|
+
it "should maximally match '1666'" do
|
452
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
453
|
+
:confidence => 1,
|
454
|
+
:utterance => '1666',
|
455
|
+
:interpretation => 'dtmf-1 dtmf-6 dtmf-6 dtmf-6'
|
456
|
+
subject.match('1666').should == expected_match
|
457
|
+
end
|
458
|
+
|
449
459
|
{
|
450
460
|
'1' => 'dtmf-1',
|
451
461
|
'16' => 'dtmf-1 dtmf-6',
|
452
462
|
'166' => 'dtmf-1 dtmf-6 dtmf-6',
|
453
|
-
'1666' => 'dtmf-1 dtmf-6 dtmf-6 dtmf-6'
|
454
463
|
}.each_pair do |input, interpretation|
|
455
464
|
it "should match '#{input}'" do
|
456
465
|
expected_match = GRXML::Match.new :mode => :dtmf,
|
@@ -486,8 +495,8 @@ module RubySpeech
|
|
486
495
|
'661' => 'dtmf-6 dtmf-6 dtmf-1',
|
487
496
|
'6661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-1'
|
488
497
|
}.each_pair do |input, interpretation|
|
489
|
-
it "should match '#{input}'" do
|
490
|
-
expected_match = GRXML::
|
498
|
+
it "should maximally match '#{input}'" do
|
499
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
491
500
|
:confidence => 1,
|
492
501
|
:utterance => input,
|
493
502
|
:interpretation => interpretation
|
@@ -564,8 +573,8 @@ module RubySpeech
|
|
564
573
|
'6661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-1',
|
565
574
|
'66661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-6 dtmf-1'
|
566
575
|
}.each_pair do |input, interpretation|
|
567
|
-
it "should match '#{input}'" do
|
568
|
-
expected_match = GRXML::
|
576
|
+
it "should maximally match '#{input}'" do
|
577
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
569
578
|
:confidence => 1,
|
570
579
|
:utterance => input,
|
571
580
|
:interpretation => interpretation
|
@@ -617,8 +626,8 @@ module RubySpeech
|
|
617
626
|
'5678#' => 'dtmf-5 dtmf-6 dtmf-7 dtmf-8 dtmf-pound',
|
618
627
|
'1111#' => 'dtmf-1 dtmf-1 dtmf-1 dtmf-1 dtmf-pound'
|
619
628
|
}.each_pair do |input, interpretation|
|
620
|
-
it "should match '#{input}'" do
|
621
|
-
expected_match = GRXML::
|
629
|
+
it "should maximally match '#{input}'" do
|
630
|
+
expected_match = GRXML::MaxMatch.new :mode => :dtmf,
|
622
631
|
:confidence => 1,
|
623
632
|
:utterance => input,
|
624
633
|
:interpretation => interpretation
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RubySpeech
|
4
|
+
module GRXML
|
5
|
+
describe MaxMatch do
|
6
|
+
it_behaves_like "match"
|
7
|
+
|
8
|
+
it { should be_a Match }
|
9
|
+
|
10
|
+
describe "equality" do
|
11
|
+
it "should never be equal to a MaxMatch" do
|
12
|
+
described_class.new.should_not eql(Match.new)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
shared_examples_for "match" do
|
2
|
+
subject do
|
3
|
+
described_class.new :mode => :dtmf,
|
4
|
+
:confidence => 1,
|
5
|
+
:utterance => '6',
|
6
|
+
:interpretation => 'foo'
|
7
|
+
end
|
8
|
+
|
9
|
+
its(:mode) { should == :dtmf }
|
10
|
+
its(:confidence) { should == 1 }
|
11
|
+
its(:utterance) { should == '6' }
|
12
|
+
its(:interpretation) { should == 'foo' }
|
13
|
+
|
14
|
+
describe "equality" do
|
15
|
+
it "should be equal when mode, confidence, utterance and interpretation are the same" do
|
16
|
+
described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo').should == described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo')
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when the mode is different" do
|
20
|
+
it "should not be equal" do
|
21
|
+
described_class.new(:mode => :dtmf).should_not == described_class.new(:mode => :speech)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when the confidence is different" do
|
26
|
+
it "should not be equal" do
|
27
|
+
described_class.new(:confidence => 1).should_not == described_class.new(:confidence => 0)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when the utterance is different" do
|
32
|
+
it "should not be equal" do
|
33
|
+
described_class.new(:utterance => '6').should_not == described_class.new(:utterance => 'foo')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "when the interpretation is different" do
|
38
|
+
it "should not be equal" do
|
39
|
+
described_class.new(:interpretation => 'foo').should_not == described_class.new(:interpretation => 'bar')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/support/matchers.rb
CHANGED
@@ -14,13 +14,7 @@ class SpeechDocMatcher
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def subject=(s)
|
17
|
-
|
18
|
-
@subject = s
|
19
|
-
else
|
20
|
-
doc = Nokogiri::XML::Document.new
|
21
|
-
doc << s.to_xml
|
22
|
-
@subject = doc
|
23
|
-
end
|
17
|
+
@subject = Nokogiri::XML(s.to_xml)
|
24
18
|
end
|
25
19
|
|
26
20
|
def failure_message
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_speech
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Langfeld
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: niceogiri
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '1.1'
|
20
20
|
- - '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.1.
|
22
|
+
version: 1.1.2
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '1.1'
|
30
30
|
- - '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.1.
|
32
|
+
version: 1.1.2
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: nokogiri
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -238,6 +238,7 @@ files:
|
|
238
238
|
- lib/ruby_speech/grxml/item.rb
|
239
239
|
- lib/ruby_speech/grxml/match.rb
|
240
240
|
- lib/ruby_speech/grxml/matcher.rb
|
241
|
+
- lib/ruby_speech/grxml/max_match.rb
|
241
242
|
- lib/ruby_speech/grxml/no_match.rb
|
242
243
|
- lib/ruby_speech/grxml/one_of.rb
|
243
244
|
- lib/ruby_speech/grxml/potential_match.rb
|
@@ -271,6 +272,7 @@ files:
|
|
271
272
|
- spec/ruby_speech/grxml/item_spec.rb
|
272
273
|
- spec/ruby_speech/grxml/match_spec.rb
|
273
274
|
- spec/ruby_speech/grxml/matcher_spec.rb
|
275
|
+
- spec/ruby_speech/grxml/max_match_spec.rb
|
274
276
|
- spec/ruby_speech/grxml/no_match_spec.rb
|
275
277
|
- spec/ruby_speech/grxml/one_of_spec.rb
|
276
278
|
- spec/ruby_speech/grxml/potential_match_spec.rb
|
@@ -296,6 +298,7 @@ files:
|
|
296
298
|
- spec/ruby_speech/ssml_spec.rb
|
297
299
|
- spec/ruby_speech_spec.rb
|
298
300
|
- spec/spec_helper.rb
|
301
|
+
- spec/support/match_examples.rb
|
299
302
|
- spec/support/matchers.rb
|
300
303
|
homepage: https://github.com/benlangfeld/ruby_speech
|
301
304
|
licenses: []
|
@@ -325,6 +328,7 @@ test_files:
|
|
325
328
|
- spec/ruby_speech/grxml/item_spec.rb
|
326
329
|
- spec/ruby_speech/grxml/match_spec.rb
|
327
330
|
- spec/ruby_speech/grxml/matcher_spec.rb
|
331
|
+
- spec/ruby_speech/grxml/max_match_spec.rb
|
328
332
|
- spec/ruby_speech/grxml/no_match_spec.rb
|
329
333
|
- spec/ruby_speech/grxml/one_of_spec.rb
|
330
334
|
- spec/ruby_speech/grxml/potential_match_spec.rb
|
@@ -350,5 +354,6 @@ test_files:
|
|
350
354
|
- spec/ruby_speech/ssml_spec.rb
|
351
355
|
- spec/ruby_speech_spec.rb
|
352
356
|
- spec/spec_helper.rb
|
357
|
+
- spec/support/match_examples.rb
|
353
358
|
- spec/support/matchers.rb
|
354
359
|
has_rdoc:
|