ruby_speech 2.1.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +17 -0
  4. data/CHANGELOG.md +144 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +314 -0
  9. data/Rakefile +34 -0
  10. data/assets/grammar-core.xsd +317 -0
  11. data/assets/grammar.xsd +37 -0
  12. data/assets/synthesis-core.xsd +445 -0
  13. data/assets/synthesis.xsd +63 -0
  14. data/assets/xml.xsd +287 -0
  15. data/ext/ruby_speech/RubySpeechGRXMLMatcher.java +64 -0
  16. data/ext/ruby_speech/RubySpeechService.java +23 -0
  17. data/ext/ruby_speech/extconf.rb +7 -0
  18. data/ext/ruby_speech/ruby_speech.c +97 -0
  19. data/lib/ruby_speech/generic_element.rb +169 -0
  20. data/lib/ruby_speech/grxml/element.rb +29 -0
  21. data/lib/ruby_speech/grxml/grammar.rb +189 -0
  22. data/lib/ruby_speech/grxml/item.rb +144 -0
  23. data/lib/ruby_speech/grxml/match.rb +16 -0
  24. data/lib/ruby_speech/grxml/matcher.rb +126 -0
  25. data/lib/ruby_speech/grxml/max_match.rb +6 -0
  26. data/lib/ruby_speech/grxml/no_match.rb +10 -0
  27. data/lib/ruby_speech/grxml/one_of.rb +31 -0
  28. data/lib/ruby_speech/grxml/potential_match.rb +10 -0
  29. data/lib/ruby_speech/grxml/rule.rb +73 -0
  30. data/lib/ruby_speech/grxml/ruleref.rb +69 -0
  31. data/lib/ruby_speech/grxml/tag.rb +29 -0
  32. data/lib/ruby_speech/grxml/token.rb +31 -0
  33. data/lib/ruby_speech/grxml.rb +39 -0
  34. data/lib/ruby_speech/nlsml/builder.rb +34 -0
  35. data/lib/ruby_speech/nlsml/document.rb +120 -0
  36. data/lib/ruby_speech/nlsml.rb +18 -0
  37. data/lib/ruby_speech/ruby_speech.jar +0 -0
  38. data/lib/ruby_speech/ssml/audio.rb +47 -0
  39. data/lib/ruby_speech/ssml/break.rb +62 -0
  40. data/lib/ruby_speech/ssml/desc.rb +24 -0
  41. data/lib/ruby_speech/ssml/element.rb +23 -0
  42. data/lib/ruby_speech/ssml/emphasis.rb +44 -0
  43. data/lib/ruby_speech/ssml/mark.rb +43 -0
  44. data/lib/ruby_speech/ssml/p.rb +25 -0
  45. data/lib/ruby_speech/ssml/phoneme.rb +72 -0
  46. data/lib/ruby_speech/ssml/prosody.rb +172 -0
  47. data/lib/ruby_speech/ssml/s.rb +25 -0
  48. data/lib/ruby_speech/ssml/say_as.rb +100 -0
  49. data/lib/ruby_speech/ssml/speak.rb +27 -0
  50. data/lib/ruby_speech/ssml/sub.rb +42 -0
  51. data/lib/ruby_speech/ssml/voice.rb +108 -0
  52. data/lib/ruby_speech/ssml.rb +39 -0
  53. data/lib/ruby_speech/version.rb +3 -0
  54. data/lib/ruby_speech/xml/language.rb +13 -0
  55. data/lib/ruby_speech/xml.rb +11 -0
  56. data/lib/ruby_speech.rb +36 -0
  57. data/ruby_speech.gemspec +42 -0
  58. data/spec/ruby_speech/grxml/grammar_spec.rb +341 -0
  59. data/spec/ruby_speech/grxml/item_spec.rb +192 -0
  60. data/spec/ruby_speech/grxml/match_spec.rb +15 -0
  61. data/spec/ruby_speech/grxml/matcher_spec.rb +688 -0
  62. data/spec/ruby_speech/grxml/max_match_spec.rb +17 -0
  63. data/spec/ruby_speech/grxml/no_match_spec.rb +17 -0
  64. data/spec/ruby_speech/grxml/one_of_spec.rb +49 -0
  65. data/spec/ruby_speech/grxml/potential_match_spec.rb +17 -0
  66. data/spec/ruby_speech/grxml/rule_spec.rb +125 -0
  67. data/spec/ruby_speech/grxml/ruleref_spec.rb +55 -0
  68. data/spec/ruby_speech/grxml/tag_spec.rb +41 -0
  69. data/spec/ruby_speech/grxml/token_spec.rb +62 -0
  70. data/spec/ruby_speech/grxml_spec.rb +339 -0
  71. data/spec/ruby_speech/nlsml_spec.rb +353 -0
  72. data/spec/ruby_speech/ssml/audio_spec.rb +121 -0
  73. data/spec/ruby_speech/ssml/break_spec.rb +100 -0
  74. data/spec/ruby_speech/ssml/desc_spec.rb +57 -0
  75. data/spec/ruby_speech/ssml/emphasis_spec.rb +110 -0
  76. data/spec/ruby_speech/ssml/mark_spec.rb +53 -0
  77. data/spec/ruby_speech/ssml/p_spec.rb +96 -0
  78. data/spec/ruby_speech/ssml/phoneme_spec.rb +65 -0
  79. data/spec/ruby_speech/ssml/prosody_spec.rb +309 -0
  80. data/spec/ruby_speech/ssml/s_spec.rb +92 -0
  81. data/spec/ruby_speech/ssml/say_as_spec.rb +71 -0
  82. data/spec/ruby_speech/ssml/speak_spec.rb +166 -0
  83. data/spec/ruby_speech/ssml/sub_spec.rb +57 -0
  84. data/spec/ruby_speech/ssml/voice_spec.rb +200 -0
  85. data/spec/ruby_speech/ssml_spec.rb +285 -0
  86. data/spec/ruby_speech_spec.rb +124 -0
  87. data/spec/spec_helper.rb +21 -0
  88. data/spec/support/match_examples.rb +43 -0
  89. data/spec/support/matchers.rb +46 -0
  90. metadata +405 -0
@@ -0,0 +1,339 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ describe GRXML do
5
+ describe "#draw" do
6
+ it "should create a GRXML document" do
7
+ GRXML.draw.should == GRXML::Grammar.new
8
+ end
9
+
10
+ context "with a root rule name specified but not found" do
11
+ it "should raise an error" do
12
+ lambda do
13
+ GRXML.draw :root => 'foo' do
14
+ rule :id => 'bar' do
15
+ '6'
16
+ end
17
+ end
18
+ end.should raise_error(InvalidChildError, "A GRXML document must have a rule matching the root rule name")
19
+ end
20
+ end
21
+
22
+ # TODO: Maybe GRXML#draw should create a Rule to pass the string
23
+ describe "when the return value of the block is a string" do
24
+ it "should be inserted into the document" do
25
+ lambda { GRXML.draw { "Hello Fred" }}.should raise_error(InvalidChildError, "A Grammar can only accept Rule and Tag as children")
26
+ end
27
+ end
28
+
29
+ it "should allow other GRXML elements to be inserted in the document" do
30
+ doc = GRXML.draw(:mode => :voice, :root => 'main') { rule :id => :main, :content => "Hello Fred" }
31
+
32
+ expected_doc = GRXML::Grammar.new(:mode => :voice, :root => 'main')
33
+ rule = GRXML::Rule.new(:id => "main")
34
+ rule << "Hello Fred"
35
+ expected_doc << rule
36
+ doc.should == expected_doc
37
+ end
38
+
39
+ it "should allow accessing methods defined outside the block" do
40
+ def foo
41
+ 'bar'
42
+ end
43
+
44
+ doc = GRXML.draw do
45
+ rule :id => foo
46
+ end
47
+
48
+ expected_doc = GRXML::Grammar.new
49
+ rule = GRXML::Rule.new(:id => foo)
50
+ expected_doc << rule
51
+ doc.should == expected_doc
52
+ end
53
+
54
+ it "should raise error if given an empty rule" do
55
+ pending 'Reject empty rules -- http://www.w3.org/TR/2002/CR-speech-grammar-20020626/#S3.1 http://www.w3.org/Voice/2003/srgs-ir/test/rule-no-empty.grxml'
56
+ lambda { GRXML.draw { rule :id => 'main' }}.should raise_error
57
+ end
58
+
59
+ it "should allow nested block return values" do
60
+ doc = RubySpeech::GRXML.draw do
61
+ rule :scope => 'public', :id => :main do
62
+ "Hello Fred"
63
+ end
64
+ end
65
+ expected_doc = GRXML::Grammar.new
66
+ expected_doc << GRXML::Rule.new(:scope => :public, :id => :main, :content => "Hello Fred")
67
+ doc.should == expected_doc
68
+ end
69
+
70
+ it "should allow nested GRXML elements" do
71
+ doc = RubySpeech::GRXML.draw do
72
+ rule :id => :main, :scope => 'public' do
73
+ string "Hello Fred. I like ninjas and pirates"
74
+ one_of do
75
+ item :content => "ninja"
76
+ item :content => "pirate"
77
+ end
78
+ end
79
+ end
80
+ rule = GRXML::Rule.new(:id => :main, :scope => 'public', :content => "Hello Fred. I like ninjas and pirates")
81
+ oneof = GRXML::OneOf.new
82
+ oneof << GRXML::Item.new(:content => "ninja")
83
+ oneof << GRXML::Item.new(:content => "pirate")
84
+ rule << oneof
85
+ expected_doc = GRXML::Grammar.new
86
+ expected_doc << rule
87
+ doc.should == expected_doc
88
+ end
89
+
90
+ # TODO: maybe turn a rule embedded in anthoer rule into a ruleref??
91
+ describe "embedding" do
92
+ context "GRXML documents" do
93
+ let :doc1 do
94
+ RubySpeech::GRXML.draw :mode => :dtmf, :root => 'digits' do
95
+ rule :id => :digits do
96
+ one_of do
97
+ item { "1" }
98
+ item { "2" }
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ let :doc2 do
105
+ doc = doc1
106
+ RubySpeech::GRXML.draw :mode => :dtmf do
107
+ embed doc
108
+ rule :id => :main do
109
+ "Hello Fred"
110
+ end
111
+ end
112
+ end
113
+
114
+ let :expected_doc do
115
+ RubySpeech::GRXML.draw :mode => :dtmf do
116
+ rule :id => :digits do
117
+ one_of do
118
+ item :content => "1"
119
+ item :content => "2"
120
+ end
121
+ end
122
+ rule :id => :main, :content => 'Hello Fred'
123
+ end
124
+ end
125
+
126
+ it "should embed the document" do
127
+ doc2.should == expected_doc
128
+ end
129
+
130
+ context "of different modes (dtmf in voice or vice-versa)" do
131
+ let :voice_doc do
132
+ GRXML.draw :mode => :voice do
133
+ embed dtmf_doc
134
+ end
135
+ end
136
+
137
+ let :dtmf_doc do
138
+ GRXML.draw :mode => :dtmf do
139
+ rule do
140
+ '6'
141
+ end
142
+ end
143
+ end
144
+
145
+ it "should raise an exception" do
146
+ lambda { voice_doc }.should raise_error(InvalidChildError, "Embedded grammars must have the same mode")
147
+ end
148
+ end
149
+ end
150
+
151
+ it "GRXML elements" do
152
+ element = GRXML::Item.new :content => "HELLO?"
153
+
154
+ doc = RubySpeech::GRXML.draw do
155
+ rule :id => :main, :scope => 'public' do
156
+ embed element
157
+ end
158
+ end
159
+
160
+ expected_doc = RubySpeech::GRXML.draw do
161
+ rule :id => :main, :scope => 'public' do
162
+ item do
163
+ "HELLO?"
164
+ end
165
+ end
166
+ end
167
+
168
+ doc.should == expected_doc
169
+ end
170
+
171
+ it "strings" do
172
+ string = "How now, brown cow?"
173
+
174
+ doc = RubySpeech::GRXML.draw do
175
+ rule :id => :main, :scope => 'public' do
176
+ embed string
177
+ end
178
+ end
179
+
180
+ expected_doc = RubySpeech::GRXML.draw do
181
+ rule :id => :main, :scope => 'public' do
182
+ string "How now, brown cow?"
183
+ end
184
+ end
185
+
186
+ doc.should == expected_doc
187
+ end
188
+ end
189
+
190
+ it "should properly escape string input" do
191
+ doc = RubySpeech::GRXML.draw do
192
+ rule { string "I <3 nachos." }
193
+ rule { "I <3 nachos." }
194
+ rule { 'I <3 nachos.' }
195
+ end
196
+ expected_doc = GRXML::Grammar.new
197
+ 3.times do
198
+ expected_doc << GRXML::Rule.new(:native_content => "I <3 nachos.")
199
+ end
200
+ doc.should == expected_doc
201
+ end
202
+
203
+ # TODO: verfify rule is in document if named in a ruleref
204
+ # TODO: ruleref must have named rule id
205
+
206
+ it "should allow all permutations of possible nested GRXML elements" do
207
+ doc = RubySpeech::GRXML.draw do
208
+ rule :id => "hello" do
209
+ string "HELLO?"
210
+ item :weight => 2.5
211
+ one_of do
212
+ item { "1" }
213
+ item { "2" }
214
+ end
215
+ ruleref :uri => '#test'
216
+ item { "last" }
217
+ end
218
+ rule :id => "test" do
219
+ string "TESTING"
220
+ end
221
+ rule :id => :hello2 do
222
+ item :weight => 5.5 do
223
+ "hello"
224
+ end
225
+ string "H...E...L...L...O?"
226
+ token { "test token" }
227
+ tag { }
228
+ item { "" }
229
+ one_of { item { "single item" } }
230
+ end
231
+ end
232
+ expected_doc = GRXML::Grammar.new
233
+ rule = GRXML::Rule.new(:id => "hello", :content => "HELLO?")
234
+ rule << GRXML::Item.new(:weight => 2.5)
235
+ oneof = GRXML::OneOf.new
236
+ 1.upto(2) { |d| oneof << GRXML::Item.new(:content => d.to_s) }
237
+ rule << oneof
238
+ rule << GRXML::Ruleref.new(:uri => '#test')
239
+ rule << GRXML::Item.new(:content => "last")
240
+ expected_doc << rule
241
+
242
+ rule = GRXML::Rule.new(:id => "test", :content => "TESTING")
243
+ expected_doc << rule
244
+
245
+ rule = GRXML::Rule.new(:id => "hello2")
246
+ rule << GRXML::Item.new(:weight => 5.5, :content => "hello")
247
+ rule << "H...E...L...L...O?"
248
+ rule << GRXML::Token.new(:content => "test token")
249
+ rule << GRXML::Tag.new
250
+ rule << GRXML::Item.new
251
+ oneof = GRXML::OneOf.new
252
+ oneof << GRXML::Item.new(:content => "single item")
253
+ rule << oneof
254
+ expected_doc << rule
255
+ doc.should == expected_doc
256
+ end
257
+
258
+ describe "importing nested tags" do
259
+ let(:item) { GRXML::Item.new(:weight => 1.5, :content => "Are you a pirate or ninja?") }
260
+ let(:string) { "Hello Fred. I like pirates and ninjas " }
261
+ let :rule do
262
+ GRXML::Rule.new(:id => :main, :scope => 'public', :content => string).tap do |rule|
263
+ rule << item
264
+ end
265
+ end
266
+
267
+ let :document do
268
+ GRXML::Grammar.new.tap { |doc| doc << rule }.to_s
269
+ end
270
+
271
+ let(:import) { GRXML.import document }
272
+
273
+ subject { import }
274
+
275
+ it "should work" do
276
+ lambda { subject }.should_not raise_error
277
+ end
278
+
279
+ it { should be_a GRXML::Grammar }
280
+
281
+ its(:children) { should == [rule] }
282
+
283
+ describe "rule" do
284
+ subject { import.children.first }
285
+ its(:children) { should == [string,item] }
286
+ end
287
+ end
288
+
289
+ it "should allow finding direct children of a particular type, matching certain attributes" do
290
+ item = GRXML::Item.new
291
+ item1 = GRXML::Item.new :weight => 0.5
292
+ item11 = GRXML::Item.new :weight => 0.5
293
+ item1 << item11
294
+ item << item1
295
+ item2 = GRXML::Item.new :weight => 0.7
296
+ item << item2
297
+ tag = GRXML::Tag.new
298
+ item << tag
299
+
300
+ item.children(:item, :weight => 0.5).should == [item1]
301
+ end
302
+
303
+ it "should be able to traverse up the tree" do
304
+ grammar = GRXML.draw do
305
+ rule :id => 'one' do
306
+ item do
307
+ 'foobar'
308
+ end
309
+ end
310
+ end
311
+
312
+ rule = grammar.children.first
313
+ rule.parent.should == grammar
314
+
315
+ item = rule.children.first
316
+ item.parent.should == rule
317
+
318
+ text = item.nokogiri_children.first
319
+ text.parent.should == item
320
+ end
321
+ end # draw
322
+
323
+ describe "manually created documents" do
324
+ it "should be able to traverse up the tree" do
325
+ grammar = GRXML::Grammar.new
326
+ rule = GRXML::Rule.new :id => 'one'
327
+ item = GRXML::Item.new
328
+ text = Nokogiri::XML::Text.new 'foobar', grammar.document
329
+ item << text
330
+ rule << item
331
+ grammar << rule
332
+
333
+ text.parent.should == item
334
+ item.parent.should == rule
335
+ rule.parent.should == grammar
336
+ end
337
+ end
338
+ end # GRXML
339
+ end # RubySpeech
@@ -0,0 +1,353 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubySpeech::NLSML do
4
+ let :example_document do
5
+ '''
6
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
7
+ <interpretation confidence="0.6">
8
+ <input mode="speech">I want to go to Pittsburgh</input>
9
+ <instance>
10
+ <airline>
11
+ <to_city>Pittsburgh</to_city>
12
+ </airline>
13
+ </instance>
14
+ </interpretation>
15
+ <interpretation confidence="0.4">
16
+ <input>I want to go to Stockholm</input>
17
+ <instance>
18
+ <airline>
19
+ <to_city>Stockholm</to_city>
20
+ </airline>
21
+ </instance>
22
+ </interpretation>
23
+ </result>
24
+ '''
25
+ end
26
+
27
+ describe 'drawing a document' do
28
+ let :expected_document do
29
+ Nokogiri::XML(example_document, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).to_xml
30
+ end
31
+
32
+ it "should allow building a document" do
33
+ document = RubySpeech::NLSML.draw(grammar: 'http://flight') do
34
+ interpretation confidence: 0.6 do
35
+ input "I want to go to Pittsburgh", mode: :speech
36
+
37
+ instance do
38
+ airline do
39
+ to_city 'Pittsburgh'
40
+ end
41
+ end
42
+ end
43
+
44
+ interpretation confidence: 0.4 do
45
+ input "I want to go to Stockholm"
46
+
47
+ instance do
48
+ airline do
49
+ to_city "Stockholm"
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ document.to_xml.should == expected_document
56
+ end
57
+
58
+ context "with a string instance" do
59
+ let :example_document do
60
+ '''
61
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
62
+ <interpretation confidence="0.6">
63
+ <input mode="speech">I want to go to Pittsburgh</input>
64
+ <instance>I want to go to Pittsburgh</instance>
65
+ </interpretation>
66
+ </result>
67
+ '''
68
+ end
69
+
70
+ it "should allow building a document" do
71
+ document = RubySpeech::NLSML.draw(grammar: 'http://flight') do
72
+ interpretation confidence: 0.6 do
73
+ input "I want to go to Pittsburgh", mode: :speech
74
+
75
+ instance "I want to go to Pittsburgh"
76
+ end
77
+ end
78
+
79
+ document.to_xml.should == expected_document
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "parsing a document" do
85
+ subject do
86
+ RubySpeech.parse example_document
87
+ end
88
+
89
+ let(:empty_result) { '<result xmlns="http://www.ietf.org/xml/ns/mrcpv2"/>' }
90
+
91
+ its(:grammar) { should == 'http://flight' }
92
+
93
+ it { should be_match }
94
+
95
+ let(:expected_best_interpretation) do
96
+ {
97
+ confidence: 0.6,
98
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
99
+ instance: { airline: { to_city: 'Pittsburgh' } },
100
+ instances: [{ airline: { to_city: 'Pittsburgh' } }]
101
+ }
102
+ end
103
+
104
+ let(:expected_interpretations) do
105
+ [
106
+ expected_best_interpretation,
107
+ {
108
+ confidence: 0.4,
109
+ input: { content: 'I want to go to Stockholm' },
110
+ instance: { airline: { to_city: 'Stockholm' } },
111
+ instances: [{ airline: { to_city: 'Stockholm' } }]
112
+ }
113
+ ]
114
+ end
115
+
116
+ its(:interpretations) { should == expected_interpretations }
117
+ its(:best_interpretation) { should == expected_best_interpretation }
118
+
119
+ it "should be equal if the XML is the same" do
120
+ subject.should be == RubySpeech.parse(example_document)
121
+ end
122
+
123
+ it "should not be equal if the XML is different" do
124
+ subject.should_not be == RubySpeech.parse(empty_result)
125
+ end
126
+
127
+ context "with an interpretation that has no instance" do
128
+ let :example_document do
129
+ '''
130
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
131
+ <interpretation confidence="0.6">
132
+ <input mode="speech">I want to go to Pittsburgh</input>
133
+ </interpretation>
134
+ <interpretation confidence="0.4">
135
+ <input>I want to go to Stockholm</input>
136
+ </interpretation>
137
+ </result>
138
+ '''
139
+ end
140
+
141
+ let(:expected_best_interpretation) do
142
+ {
143
+ confidence: 0.6,
144
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
145
+ instance: nil,
146
+ instances: []
147
+ }
148
+ end
149
+
150
+ let(:expected_interpretations) do
151
+ [
152
+ expected_best_interpretation,
153
+ {
154
+ confidence: 0.4,
155
+ input: { content: 'I want to go to Stockholm' },
156
+ instance: nil,
157
+ instances: []
158
+ }
159
+ ]
160
+ end
161
+
162
+ its(:interpretations) { should == expected_interpretations }
163
+ its(:best_interpretation) { should == expected_best_interpretation }
164
+ end
165
+
166
+ context "with a string instance" do
167
+ let :example_document do
168
+ '''
169
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
170
+ <interpretation confidence="0.6">
171
+ <input mode="speech">I want to go to Pittsburgh</input>
172
+ <instance>I want to go to Pittsburgh</instance>
173
+ </interpretation>
174
+ </result>
175
+ '''
176
+ end
177
+
178
+ let(:expected_best_interpretation) do
179
+ {
180
+ confidence: 0.6,
181
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
182
+ instance: 'I want to go to Pittsburgh',
183
+ instances: ['I want to go to Pittsburgh']
184
+ }
185
+ end
186
+
187
+ let(:expected_interpretations) do
188
+ [expected_best_interpretation]
189
+ end
190
+
191
+ its(:interpretations) { should == expected_interpretations }
192
+ its(:best_interpretation) { should == expected_best_interpretation }
193
+ end
194
+
195
+ context "without any interpretations" do
196
+ subject do
197
+ RubySpeech.parse empty_result
198
+ end
199
+
200
+ it { should_not be_match }
201
+ end
202
+
203
+ context "with interpretations out of confidence order" do
204
+ let :example_document do
205
+ '''
206
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
207
+ <interpretation confidence="0.4">
208
+ <input>I want to go to Stockholm</input>
209
+ <instance>
210
+ <airline>
211
+ <to_city>Stockholm</to_city>
212
+ </airline>
213
+ </instance>
214
+ </interpretation>
215
+ <interpretation confidence="0.6">
216
+ <input mode="speech">I want to go to Pittsburgh</input>
217
+ <instance>
218
+ <airline>
219
+ <to_city>Pittsburgh</to_city>
220
+ </airline>
221
+ </instance>
222
+ </interpretation>
223
+ </result>
224
+ '''
225
+ end
226
+
227
+ its(:interpretations) { should == expected_interpretations }
228
+ its(:best_interpretation) { should == expected_best_interpretation }
229
+ end
230
+
231
+ context "with multiple instances for a single interpretation" do
232
+ let :example_document do
233
+ '''
234
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
235
+ <interpretation confidence="1">
236
+ <input mode="speech">I want to go to Boston</input>
237
+ <instance>
238
+ <airline>
239
+ <to_city>Boston, MA</to_city>
240
+ </airline>
241
+ </instance>
242
+ <instance>
243
+ <airline>
244
+ <to_city>Boston, UK</to_city>
245
+ </airline>
246
+ </instance>
247
+ </interpretation>
248
+ </result>
249
+ '''
250
+ end
251
+
252
+ let(:expected_interpretation) do
253
+ {
254
+ confidence: 1.0,
255
+ input: { content: 'I want to go to Boston', mode: :speech },
256
+ instance: { airline: { to_city: 'Boston, MA' } },
257
+ instances: [
258
+ { airline: { to_city: 'Boston, MA' } },
259
+ { airline: { to_city: 'Boston, UK' } }
260
+ ]
261
+ }
262
+ end
263
+
264
+ its(:interpretations) { should == [expected_interpretation] }
265
+ its(:best_interpretation) { should == expected_interpretation }
266
+ end
267
+
268
+ context "with no namespace" do
269
+ let :example_document do
270
+ '''
271
+ <result grammar="http://flight">
272
+ <interpretation confidence="0.6">
273
+ <input mode="speech">I want to go to Pittsburgh</input>
274
+ <instance>
275
+ <airline>
276
+ <to_city>Pittsburgh</to_city>
277
+ </airline>
278
+ </instance>
279
+ </interpretation>
280
+ <interpretation confidence="0.4">
281
+ <input>I want to go to Stockholm</input>
282
+ <instance>
283
+ <airline>
284
+ <to_city>Stockholm</to_city>
285
+ </airline>
286
+ </instance>
287
+ </interpretation>
288
+ </result>
289
+ '''
290
+ end
291
+
292
+ its(:interpretations) { should == expected_interpretations }
293
+ its(:best_interpretation) { should == expected_best_interpretation }
294
+ end
295
+
296
+ context "with a single interpretation with a nomatch input" do
297
+ let :example_document do
298
+ '''
299
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
300
+ <interpretation>
301
+ <input>
302
+ <nomatch/>
303
+ </input>
304
+ </interpretation>
305
+ </result>
306
+ '''
307
+ end
308
+
309
+ it { should_not be_match }
310
+ end
311
+
312
+ context "with multiple interpretations where one is a nomatch input" do
313
+ let :example_document do
314
+ '''
315
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
316
+ <interpretation confidence="0.6">
317
+ <input mode="speech">I want to go to Pittsburgh</input>
318
+ <instance>
319
+ <airline>
320
+ <to_city>Pittsburgh</to_city>
321
+ </airline>
322
+ </instance>
323
+ </interpretation>
324
+ <interpretation>
325
+ <input>
326
+ <nomatch/>
327
+ </input>
328
+ </interpretation>
329
+ </result>
330
+ '''
331
+ end
332
+
333
+ it { should be_match }
334
+ end
335
+
336
+ context "with a single interpretation with a noinput" do
337
+ let :example_document do
338
+ '''
339
+ <result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
340
+ <interpretation>
341
+ <input>
342
+ <noinput/>
343
+ </input>
344
+ </interpretation>
345
+ </result>
346
+ '''
347
+ end
348
+
349
+ it { should_not be_match }
350
+ it { should be_noinput }
351
+ end
352
+ end
353
+ end