| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Implementation of the speech rule engine. | 6 * @fileoverview Implementation of the speech rule engine. |
| 7 * | 7 * |
| 8 * The speech rule engine chooses and applies speech rules. Rules are chosen | 8 * The speech rule engine chooses and applies speech rules. Rules are chosen |
| 9 * from a set of rule stores wrt. their applicability to a node in a particular | 9 * from a set of rule stores wrt. their applicability to a node in a particular |
| 10 * markup type such as MathML or HTML. Rules are dispatched either by | 10 * markup type such as MathML or HTML. Rules are dispatched either by |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 /** | 48 /** |
| 49 * Parameterizes the speech rule engine. | 49 * Parameterizes the speech rule engine. |
| 50 * @param {cvox.BaseRuleStore} store A speech rule store. | 50 * @param {cvox.BaseRuleStore} store A speech rule store. |
| 51 */ | 51 */ |
| 52 cvox.SpeechRuleEngine.prototype.parameterize = function(store) { | 52 cvox.SpeechRuleEngine.prototype.parameterize = function(store) { |
| 53 try { | 53 try { |
| 54 store.initialize(); | 54 store.initialize(); |
| 55 } catch (err) { | 55 } catch (err) { |
| 56 if (err.name == 'StoreError') { | 56 if (err.name == 'StoreError') { |
| 57 console.log('Store Error:', err.message); | 57 console.log('Store Error:', err.message); |
| 58 } | 58 } else { |
| 59 else { | |
| 60 throw err; | 59 throw err; |
| 61 } | 60 } |
| 62 } | 61 } |
| 63 this.activeStore_ = store; | 62 this.activeStore_ = store; |
| 64 }; | 63 }; |
| 65 | 64 |
| 66 | 65 |
| 67 /** | 66 /** |
| 68 * Parameterizes the dynamic constraint annotation for the speech rule | 67 * Parameterizes the dynamic constraint annotation for the speech rule |
| 69 * engine. This is a separate function as this can be done interactively, while | 68 * engine. This is a separate function as this can be done interactively, while |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 case cvox.SpeechRule.Type.NODE: | 138 case cvox.SpeechRule.Type.NODE: |
| 140 var selected = this.activeStore_.applyQuery(node, content); | 139 var selected = this.activeStore_.applyQuery(node, content); |
| 141 if (selected) { | 140 if (selected) { |
| 142 navs = this.evaluateTree_(selected); | 141 navs = this.evaluateTree_(selected); |
| 143 } | 142 } |
| 144 break; | 143 break; |
| 145 case cvox.SpeechRule.Type.MULTI: | 144 case cvox.SpeechRule.Type.MULTI: |
| 146 selected = this.activeStore_.applySelector(node, content); | 145 selected = this.activeStore_.applySelector(node, content); |
| 147 if (selected.length > 0) { | 146 if (selected.length > 0) { |
| 148 navs = this.evaluateNodeList_( | 147 navs = this.evaluateNodeList_( |
| 149 selected, | 148 selected, component['sepFunc'], |
| 150 component['sepFunc'], | |
| 151 this.constructString(node, component['separator']), | 149 this.constructString(node, component['separator']), |
| 152 component['ctxtFunc'], | 150 component['ctxtFunc'], |
| 153 this.constructString(node, component['context'])); | 151 this.constructString(node, component['context'])); |
| 154 } | 152 } |
| 155 break; | 153 break; |
| 156 case cvox.SpeechRule.Type.TEXT: | 154 case cvox.SpeechRule.Type.TEXT: |
| 157 selected = this.constructString(node, content); | 155 selected = this.constructString(node, content); |
| 158 if (selected) { | 156 if (selected) { |
| 159 navs = [new cvox.NavDescription({text: selected})]; | 157 navs = [new cvox.NavDescription({text: selected})]; |
| 160 } | 158 } |
| 161 break; | 159 break; |
| 162 case cvox.SpeechRule.Type.PERSONALITY: | 160 case cvox.SpeechRule.Type.PERSONALITY: |
| 163 default: | 161 default: |
| 164 navs = [new cvox.NavDescription({text: content})]; | 162 navs = [new cvox.NavDescription({text: content})]; |
| 165 } | 163 } |
| 166 // Adding overall context if it exists. | 164 // Adding overall context if it exists. |
| 167 if (navs[0] && component['context'] && | 165 if (navs[0] && component['context'] && |
| 168 component.type != cvox.SpeechRule.Type.MULTI) { | 166 component.type != cvox.SpeechRule.Type.MULTI) { |
| 169 navs[0]['context'] = | 167 navs[0]['context'] = this.constructString(node, component['context']) + |
| 170 this.constructString(node, component['context']) + | 168 (navs[0]['context'] || ''); |
| 171 (navs[0]['context'] || ''); | |
| 172 } | 169 } |
| 173 // Adding personality to the nav descriptions. | 170 // Adding personality to the nav descriptions. |
| 174 result = result.concat(this.addPersonality_(navs, component)); | 171 result = result.concat(this.addPersonality_(navs, component)); |
| 175 } | 172 } |
| 176 return result; | 173 return result; |
| 177 }; | 174 }; |
| 178 | 175 |
| 179 | 176 |
| 180 /** | 177 /** |
| 181 * Evaluates a list of nodes into a list of navigation descriptions. | 178 * Evaluates a list of nodes into a list of navigation descriptions. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 192 * @private | 189 * @private |
| 193 */ | 190 */ |
| 194 cvox.SpeechRuleEngine.prototype.evaluateNodeList_ = function( | 191 cvox.SpeechRuleEngine.prototype.evaluateNodeList_ = function( |
| 195 nodes, sepFunc, separator, ctxtFunc, context) { | 192 nodes, sepFunc, separator, ctxtFunc, context) { |
| 196 if (nodes == []) { | 193 if (nodes == []) { |
| 197 return []; | 194 return []; |
| 198 } | 195 } |
| 199 var sep = separator || ''; | 196 var sep = separator || ''; |
| 200 var cont = context || ''; | 197 var cont = context || ''; |
| 201 var cFunc = this.activeStore_.contextFunctions.lookup(ctxtFunc); | 198 var cFunc = this.activeStore_.contextFunctions.lookup(ctxtFunc); |
| 202 var ctxtClosure = cFunc ? cFunc(nodes, cont) : function() {return cont;}; | 199 var ctxtClosure = cFunc ? cFunc(nodes, cont) : function() { |
| 200 return cont; |
| 201 }; |
| 203 var sFunc = this.activeStore_.contextFunctions.lookup(sepFunc); | 202 var sFunc = this.activeStore_.contextFunctions.lookup(sepFunc); |
| 204 var sepClosure = sFunc ? sFunc(nodes, sep) : function() {return sep;}; | 203 var sepClosure = sFunc ? sFunc(nodes, sep) : function() { |
| 204 return sep; |
| 205 }; |
| 205 var result = []; | 206 var result = []; |
| 206 for (var i = 0, node; node = nodes[i]; i++) { | 207 for (var i = 0, node; node = nodes[i]; i++) { |
| 207 var navs = this.evaluateTree_(node); | 208 var navs = this.evaluateTree_(node); |
| 208 if (navs.length > 0) { | 209 if (navs.length > 0) { |
| 209 navs[0]['context'] = ctxtClosure() + (navs[0]['context'] || ''); | 210 navs[0]['context'] = ctxtClosure() + (navs[0]['context'] || ''); |
| 210 result = result.concat(navs); | 211 result = result.concat(navs); |
| 211 if (i < nodes.length - 1) { | 212 if (i < nodes.length - 1) { |
| 212 var text = sepClosure(); | 213 var text = sepClosure(); |
| 213 if (text) { | 214 if (text) { |
| 214 result.push(new cvox.NavDescription({text: text})); | 215 result.push(new cvox.NavDescription({text: text})); |
| 215 } | 216 } |
| 216 } | 217 } |
| 217 } | 218 } |
| 218 } | 219 } |
| 219 return result; | 220 return result; |
| 220 }; | 221 }; |
| 221 | 222 |
| 222 | 223 |
| 223 /** | 224 /** |
| 224 * Maps properties in speech rules to personality properties. | 225 * Maps properties in speech rules to personality properties. |
| 225 * @type {{pitch : string, | 226 * @type {{pitch : string, |
| 226 * rate: string, | 227 * rate: string, |
| 227 * volume: string, | 228 * volume: string, |
| 228 * pause: string}} | 229 * pause: string}} |
| 229 * @const | 230 * @const |
| 230 */ | 231 */ |
| 231 cvox.SpeechRuleEngine.propMap = {'pitch': cvox.AbstractTts.RELATIVE_PITCH, | 232 cvox.SpeechRuleEngine.propMap = { |
| 232 'rate': cvox.AbstractTts.RELATIVE_RATE, | 233 'pitch': cvox.AbstractTts.RELATIVE_PITCH, |
| 233 'volume': cvox.AbstractTts.RELATIVE_VOLUME, | 234 'rate': cvox.AbstractTts.RELATIVE_RATE, |
| 234 'pause': cvox.AbstractTts.PAUSE | 235 'volume': cvox.AbstractTts.RELATIVE_VOLUME, |
| 235 }; | 236 'pause': cvox.AbstractTts.PAUSE |
| 237 }; |
| 236 | 238 |
| 237 | 239 |
| 238 /** | 240 /** |
| 239 * Adds personality to every Navigation Descriptions in input list. | 241 * Adds personality to every Navigation Descriptions in input list. |
| 240 * @param {Array<cvox.NavDescription>} navs A list of Navigation descriptions. | 242 * @param {Array<cvox.NavDescription>} navs A list of Navigation descriptions. |
| 241 * @param {Object} props Property dictionary. | 243 * @param {Object} props Property dictionary. |
| 242 * TODO (sorge) Fully specify, when we have finalised the speech rule | 244 * TODO (sorge) Fully specify, when we have finalised the speech rule |
| 243 * format. | 245 * format. |
| 244 * @return {Array<cvox.NavDescription>} The modified array. | 246 * @return {Array<cvox.NavDescription>} The modified array. |
| 245 * @private | 247 * @private |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 cvox.SpeechRuleEngine.debugMode = false; | 313 cvox.SpeechRuleEngine.debugMode = false; |
| 312 | 314 |
| 313 | 315 |
| 314 /** | 316 /** |
| 315 * Give debug output. | 317 * Give debug output. |
| 316 * @param {...*} output Rest elements of debug output. | 318 * @param {...*} output Rest elements of debug output. |
| 317 */ | 319 */ |
| 318 cvox.SpeechRuleEngine.outputDebug = function(output) { | 320 cvox.SpeechRuleEngine.outputDebug = function(output) { |
| 319 if (cvox.SpeechRuleEngine.debugMode) { | 321 if (cvox.SpeechRuleEngine.debugMode) { |
| 320 var outputList = Array.prototype.slice.call(arguments, 0); | 322 var outputList = Array.prototype.slice.call(arguments, 0); |
| 321 console.log.apply(console, | 323 console.log.apply( |
| 322 ['Speech Rule Engine Debugger:'].concat(outputList)); | 324 console, ['Speech Rule Engine Debugger:'].concat(outputList)); |
| 323 } | 325 } |
| 324 }; | 326 }; |
| 325 | 327 |
| 326 | 328 |
| 327 /** | 329 /** |
| 328 * Prints the list of all current rules in ChromeVox to the console. | 330 * Prints the list of all current rules in ChromeVox to the console. |
| 329 * @return {string} A textual representation of all rules in the speech rule | 331 * @return {string} A textual representation of all rules in the speech rule |
| 330 * engine. | 332 * engine. |
| 331 */ | 333 */ |
| 332 cvox.SpeechRuleEngine.prototype.toString = function() { | 334 cvox.SpeechRuleEngine.prototype.toString = function() { |
| 333 var allRules = this.activeStore_.findAllRules(function(x) {return true;}); | 335 var allRules = this.activeStore_.findAllRules(function(x) { |
| 334 return allRules.map(function(rule) {return rule.toString();}). | 336 return true; |
| 335 join('\n'); | 337 }); |
| 338 return allRules |
| 339 .map(function(rule) { |
| 340 return rule.toString(); |
| 341 }) |
| 342 .join('\n'); |
| 336 }; | 343 }; |
| 337 | 344 |
| 338 | 345 |
| 339 /** | 346 /** |
| 340 * Test the precondition of a speech rule in debugging mode. | 347 * Test the precondition of a speech rule in debugging mode. |
| 341 * @param {cvox.SpeechRule} rule A speech rule. | 348 * @param {cvox.SpeechRule} rule A speech rule. |
| 342 * @param {!Node} node DOM node to test applicability of the rule. | 349 * @param {!Node} node DOM node to test applicability of the rule. |
| 343 */ | 350 */ |
| 344 cvox.SpeechRuleEngine.debugSpeechRule = function(rule, node) { | 351 cvox.SpeechRuleEngine.debugSpeechRule = function(rule, node) { |
| 345 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; | 352 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; |
| 346 if (store) { | 353 if (store) { |
| 347 var prec = rule.precondition; | 354 var prec = rule.precondition; |
| 348 cvox.SpeechRuleEngine.outputDebug( | 355 cvox.SpeechRuleEngine.outputDebug( |
| 349 prec.query, store.applyQuery(node, prec.query)); | 356 prec.query, store.applyQuery(node, prec.query)); |
| 350 prec.constraints.forEach( | 357 prec.constraints.forEach(function(cstr) { |
| 351 function(cstr) { | 358 cvox.SpeechRuleEngine.outputDebug( |
| 352 cvox.SpeechRuleEngine.outputDebug( | 359 cstr, store.applyConstraint(node, cstr)); |
| 353 cstr, store.applyConstraint(node, cstr));}); | 360 }); |
| 354 } | 361 } |
| 355 }; | 362 }; |
| 356 | 363 |
| 357 | 364 |
| 358 /** | 365 /** |
| 359 * Test the precondition of a speech rule in debugging mode. | 366 * Test the precondition of a speech rule in debugging mode. |
| 360 * @param {string} name Rule to debug. | 367 * @param {string} name Rule to debug. |
| 361 * @param {!Node} node DOM node to test applicability of the rule. | 368 * @param {!Node} node DOM node to test applicability of the rule. |
| 362 */ | 369 */ |
| 363 cvox.SpeechRuleEngine.debugNamedSpeechRule = function(name, node) { | 370 cvox.SpeechRuleEngine.debugNamedSpeechRule = function(name, node) { |
| 364 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; | 371 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; |
| 365 var allRules = store.findAllRules( | 372 var allRules = store.findAllRules(function(rule) { |
| 366 function(rule) {return rule.name == name;}); | 373 return rule.name == name; |
| 374 }); |
| 367 for (var i = 0, rule; rule = allRules[i]; i++) { | 375 for (var i = 0, rule; rule = allRules[i]; i++) { |
| 368 cvox.SpeechRuleEngine.outputDebug('Rule', name, 'number', i); | 376 cvox.SpeechRuleEngine.outputDebug('Rule', name, 'number', i); |
| 369 cvox.SpeechRuleEngine.debugSpeechRule(rule, node); | 377 cvox.SpeechRuleEngine.debugSpeechRule(rule, node); |
| 370 } | 378 } |
| 371 }; | 379 }; |
| OLD | NEW |