TalAter / annyang

:speech_balloon: Speech recognition for your site
https://www.talater.com/annyang/
MIT License
6.57k stars 1.05k forks source link

Using variables to define commands dynamically inside an advanced regular expression object with REGEXP and CALLBACK properties #426

Closed The-Linguist closed 3 years ago

The-Linguist commented 3 years ago

Let's say the user has to answer the following question via annyang,

The simple way is,

const correctAnswerFunction = function() { alert("Yes, that's right. Your answer is correct!"); };
const commands =    {
  'meat': correctAnswerFunction
};
annyang.addCommands(commands);

However, instead of this, I can create answer.txt file which contains nothing but meat. And use fetch() or XHR method to get that "meat" as a string. Then create a variable which works like let correctAnswer = "meat"; In this case,

let commands = {};
commands[correctAnswer] = correctAnswerFunction;
annyang.addCommands(commands);

works. And thus the architecture of the app is now easily expandable. It is also good that .txt files are easy to modify for non-coder people in the team. Then, what we definitely want to do is, accept "meet" as well as "meat" as the correct answer. Therefore change answer.txt file so that it contains meat|meet. And our variable is like let correctAnswer = "meat|meet";

In this case, how can we use the correctAnswer variable inside an advanced command object with 'regexp' and 'callback' properties? Main example of regular expressions to define your commands is here.

Your answer will be useful for those who are not familiar with the /^ and $/ syntax.

P.S. We could also put (meat|meet) inside answer.txt instead of just meat|meet.

TalAter commented 3 years ago

It really is unrelated to annyang and more domain specific to how you use JavaScript. But let me try.

// iterate over an array of answers fetched from the .txt file
['meat|meet', 'soup|shoop'].forEach(answer => {
  annyang.addCommands({
    [answer]: {'regexp': new RegExp(`^${answer}$`), callback: winFn}
  })
});

I didn't check the syntax, but you should get the gist of it from this.

The-Linguist commented 3 years ago

Thanks to your idea and guidance, I was able to get the results I wanted. Let me post my working code for those who may need it. NOTICE: This is for single word commands only! But you can build on the idea if you want.

let whatWeGetFromTxtFile = "meat meet beat beet"; // We will use the SPACE character like an OR or ||
const magicalSelectionRegex = /\S+/gim; // Regular expression to get each and every word (including non-english and/or non-latin words) separated by a space (i.e. either the Latin space or the Asian “big space”)
let eachWordArray = whatWeGetFromTxtFile.match(magicalSelectionRegex);
console.log("All of the words separated: " + eachWordArray);
let commands = {};
for(i=0;i<eachWordArray.length;i++)
{
  let oneOfTheWords = eachWordArray[i];
  console.log( "array["+i+"] --> "+ oneOfTheWords);
  commands[oneOfTheWords] = stopListeningAndProceedToWhateverComesNextFunction;
}
annyang.addCommands(commands);