Skip to content

Instantly share code, notes, and snippets.

@jchandra74
Last active April 27, 2024 04:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jchandra74/750b9bbe639a961b660701b9448dbddb to your computer and use it in GitHub Desktop.
Save jchandra74/750b9bbe639a961b660701b9448dbddb to your computer and use it in GitHub Desktop.
Angular Speech API Times Table Quiz for Kids
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GistRun</title>
<link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container" ng-app="app" ng-controller="pageCtrl as page">
<div class="well well-sm">
<p>Say the answer or type in your answer and press <strong>Enter</strong></p>
</div>
<form ng-submit="page.calculateResult()">
<div class="row" ng-cloak>
<div class="col-xs-2 text-center">
<h1>{{page.num1}}</h1>
</div>
<div class="col-xs-1 text-center">
<h1>x</h1>
</div>
<div class="col-xs-2 text-center">
<h1>{{page.num2}}</h1>
</div>
<div class="col-xs-1 text-center">
<h1>=</h1>
</div>
<div class="col-xs-6">
<div class="form-group">
<input type="text" class="form-control text-right" style="width:96px;height:72px;font-size:36px" ng-model="page.guess">
</div>
</div>
<div class="col-xs-12" ng-if="page.calculated">
<h1 class="text-danger" ng-if="!page.correct">WRONG!</h1>
<h1 class="text-success" ng-if="page.correct">CORRECT!</h1>
</div>
</div>
<div class="row" ng-cloak>
<div class="col-xs-12">
<h1 ng-if="page.calculated">{{page.num1}} x {{page.num2}} is <span class="text-primary">{{page.num3}}</span>.</h1>
</div>
</div>
</form>
</div>
<script data-require="angular.js@1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
(function() {
angular
.module('app',[]);
//Speech Service
angular
.module('app')
.factory('speechSvc', speechSvc);
speechSvc.$inject = ['$q', '$log'];
function speechSvc($q, $log) {
var utterance = new SpeechSynthesisUtterance();
var recognizer = new webkitSpeechRecognition();
var svc = {
init: setupVoice,
say : say,
listen: listen,
stopListening: stopListening
}
return svc;
function setupVoice() {
var dfd = $q.defer();
var voices = window.speechSynthesis.getVoices();
window.speechSynthesis.onvoiceschanged = () => {
voices = window.speechSynthesis.getVoices();
utterance.voice = voices[3];
dfd.resolve(true);
};
return dfd.promise;
}
function stopListening() {
recognizer.stop();
$log.info('Stopped listening.');
}
function say(text) {
var dfd = $q.defer();
utterance.text = text;
utterance.onend = (e) => {
if (e.returnValue)
dfd.resolve(true);
else
dfd.reject(false);
};
utterance.onerror = (e) => {
dfd.reject(e);
};
window.speechSynthesis.speak(utterance);
return dfd.promise;
}
function listen() {
$log.info('Listening...');
var dfd = $q.defer();
recognizer.onresult = (e) => {
console.log('Result:' + e);
dfd.resolve(e);
};
recognizer.start();
return dfd.promise;
}
}
//Page Controller
angular
.module('app')
.controller('pageCtrl', pageCtrl);
pageCtrl.$inject = ['$q', '$log', 'speechSvc'];
function pageCtrl($q, $log, speechSvc) {
//jshint validthis: true
var self = this;
self.num1 = 0;
self.num2 = 0;
self.guess = '';
self.calculated = false;
self.correct = false;
self.calculateResult = calculateResult;
activate();
//from MDN
function getRandomIntInclusive(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function askMultiplicationQuestion() {
self.calculated = false;
self.correct = false;
self.num1 = getRandomIntInclusive(2, 12);
self.num2 = getRandomIntInclusive(2, 12);
self.guess = '';
return speechSvc.say(`What is ${self.num1} times ${self.num2}?`);
}
function evaluateAnswer(e) {
var result = e.results[0][0];
$log.info(result.transcript, result.confidence);
self.guess = result.transcript;
var response = calculateResultInternal();
return speechSvc.say(`You said ${self.guess}. ${response}`)
.then(e => {
$q.when(true);
});
}
function calculateResultInternal() {
var mult = self.num1 * self.num2;
self.num3 = mult;
self.calculated = true;
var guessNumber = parseInt(self.guess, 10);
self.correct = mult === guessNumber;
return self.correct
? `That is correct!`
: `That is incorrect. ${self.num1} times ${self.num2} is ${mult}`;
}
function calculateResult() {
var response = calculateResultInternal();
speechSvc.stopListening();
speechSvc
.say(`You typed in ${self.guess}. ${response}`)
.then(startQuiz);
}
function startQuiz() {
return askMultiplicationQuestion()
.then(speechSvc.listen)
.then(evaluateAnswer)
.then(startQuiz);
}
function activate() {
speechSvc
.init()
.then(startQuiz)
.then((e) => {
$log.info('Done');
});
}
}
}());
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment