|
|
@@ -7,7 +7,8 @@ var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEv |
|
|
|
// #region state management |
|
|
|
var state = ''; |
|
|
|
var question = 0; |
|
|
|
var rePrompt = false; |
|
|
|
// currently disabled feature |
|
|
|
// var rePrompt = false; |
|
|
|
var partTwo = false; |
|
|
|
var questionThreeCount = 0; |
|
|
|
var strike = 0; |
|
|
@@ -20,20 +21,25 @@ const QUESTION_TWO = 'Nennen Sie mir bitte so viel Dinge wie möglich, die man i |
|
|
|
const QUESTION_THREE = 'Ich werde Ihnen jetzt eine Zahlenreihe nennen, die Sie mir dann bitte in umgekehrter Reihenfolge wiederholen sollen. Wenn ich beispielsweise, vier - fünf sage, dann sagen Sie bitte, fünf - vier.'; |
|
|
|
const QUESTION_FOUR = 'Wir kommen nun zur vierten Frage. Bitte zählen Sie von 76 an rückwärts. Nennen Sie die Zahlen abwechselnd als ganze Zahlen und als einzelne Ziffern. Zum Beispiel:'; |
|
|
|
const QUESTION_FOUR_PT2 = ['34', '3, 3', '32', '3, 1']; |
|
|
|
const QUESTION_FIVE = 'Ganz am Anfang dieses Tests habe ich Ihnen 10 Worte genannt. Können Sie sich noch an diese Worte erinnern?'; |
|
|
|
// #endregion |
|
|
|
|
|
|
|
const FINISH = 'Sie sind jetzt fertig mit dem Test, Vielen Dank.'; |
|
|
|
|
|
|
|
// #region intents |
|
|
|
const WELCOME_INTENT = 'Default Welcome Intent'; |
|
|
|
const WELCOME_FOLLOWUP_YES = 'Default Welcome Intent - yes'; |
|
|
|
const WELCOME_FOLLOWUP_NO = 'Default Welcome Intent - no'; |
|
|
|
const MORE_TIME = 'Add Time Intent'; |
|
|
|
const MORE_TIME_YES = 'Add Time Intent - yes'; |
|
|
|
const MORE_TIME_NO = 'Add Time Intent - no'; |
|
|
|
// currently disabled feature |
|
|
|
// const MORE_TIME = 'Add Time Intent'; |
|
|
|
// const MORE_TIME_YES = 'Add Time Intent - yes'; |
|
|
|
// const MORE_TIME_NO = 'Add Time Intent - no'; |
|
|
|
const QUIT_INTENT = 'Quit Intent'; |
|
|
|
const FALLBACK_INTENT = 'Default Fallback Intent'; |
|
|
|
const HELP_INTENT = 'Help Intent'; |
|
|
|
const CHOOSE_QUESTION = 'Frage_Starten'; |
|
|
|
const NEXT_QUESTION = 'Nächste Frage'; |
|
|
|
// disabled feature |
|
|
|
// const NEXT_QUESTION = 'Nächste Frage'; |
|
|
|
// #endregion |
|
|
|
|
|
|
|
// #region questions and expected results |
|
|
@@ -102,7 +108,7 @@ recognition.lang = 'de-DE'; |
|
|
|
recognition.maxAlternatives = 1; |
|
|
|
recognition.continuous = true; |
|
|
|
var answerQuery = ''; |
|
|
|
var skipRecording = false; |
|
|
|
var proceedWithRecording = false; |
|
|
|
// #endregion |
|
|
|
|
|
|
|
// #region speech synthesis initialization |
|
|
@@ -125,23 +131,11 @@ window.speechSynthesis.onvoiceschanged = function () { |
|
|
|
}; |
|
|
|
|
|
|
|
speechsynth.onend = function (event) { |
|
|
|
switch (question) { |
|
|
|
case 1: |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
break; |
|
|
|
case 4: |
|
|
|
break; |
|
|
|
case 5: |
|
|
|
break; |
|
|
|
} |
|
|
|
if (!skipRecording) { |
|
|
|
if (proceedWithRecording) { |
|
|
|
recognition.start(); |
|
|
|
console.log('reocgnition started. Question: ' + question); |
|
|
|
} |
|
|
|
skipRecording = false; |
|
|
|
proceedWithRecording = false; |
|
|
|
diagnosticPara.textContent = ''; |
|
|
|
console.log('global speech end'); |
|
|
|
}; |
|
|
@@ -156,7 +150,6 @@ ws.onopen = function () { |
|
|
|
ws.onmessage = function (payload) { |
|
|
|
var dialogflowResult = JSON.parse(payload.data); |
|
|
|
checkIntent(dialogflowResult); |
|
|
|
// document.querySelector('h1').innerHTML = dialogflowResult.intent.displayName; |
|
|
|
}; |
|
|
|
// #endregion |
|
|
|
|
|
|
@@ -165,48 +158,52 @@ function checkIntent (result) { |
|
|
|
switch (result.intent.displayName) { |
|
|
|
case QUIT_INTENT: |
|
|
|
state = 'quit'; |
|
|
|
if (timerId !== undefined) { |
|
|
|
clearTimeout(timerId); |
|
|
|
} |
|
|
|
skipRecording = true; |
|
|
|
stopRecognitionFallback(); |
|
|
|
speak('Beende die Durchführung.'); |
|
|
|
break; |
|
|
|
case WELCOME_INTENT: |
|
|
|
state = 'detect'; |
|
|
|
proceedWithRecording = true; |
|
|
|
speak(result.fulfillmentText); |
|
|
|
break; |
|
|
|
case WELCOME_FOLLOWUP_YES: |
|
|
|
startQuestion(1); |
|
|
|
break; |
|
|
|
case WELCOME_FOLLOWUP_NO: |
|
|
|
skipRecording = true; |
|
|
|
speak('Okay, Danke fürs Benutzen.'); |
|
|
|
break; |
|
|
|
case MORE_TIME: |
|
|
|
state = 'detect'; |
|
|
|
speak('Brauchen Sie noch etwas Zeit?'); |
|
|
|
break; |
|
|
|
case MORE_TIME_YES: |
|
|
|
rePrompt = true; |
|
|
|
state = 'answer'; |
|
|
|
speak('Alles klar'); |
|
|
|
speak('Alles klar. Danke fürs Benutzen.'); |
|
|
|
break; |
|
|
|
case MORE_TIME_NO: |
|
|
|
skipRecording = true; |
|
|
|
state = 'answer'; |
|
|
|
speak('Verstanden'); |
|
|
|
/// /// /// currently disabled feature |
|
|
|
// case MORE_TIME: |
|
|
|
// state = 'detect'; |
|
|
|
// proceedWithRecording = true; |
|
|
|
// speak('Brauchen Sie noch etwas Zeit?'); |
|
|
|
// break; |
|
|
|
// case MORE_TIME_YES: |
|
|
|
// rePrompt = true; |
|
|
|
// state = 'answer'; |
|
|
|
// proceedWithRecording = true; |
|
|
|
// speak('Alles klar'); |
|
|
|
// break; |
|
|
|
// case MORE_TIME_NO: |
|
|
|
// state = 'answer'; |
|
|
|
// speak('Verstanden'); |
|
|
|
// recognition.stop(); |
|
|
|
// ws.send(answerQuery); |
|
|
|
// break; |
|
|
|
// case CHOOSE_QUESTION: |
|
|
|
// question = result.parameters.fields.num.numberValue; |
|
|
|
// state = 'answer'; |
|
|
|
// handleQuestion(); |
|
|
|
// break; |
|
|
|
/// /// /// |
|
|
|
case HELP_INTENT: |
|
|
|
stopRecognitionFallback(); |
|
|
|
recognition.stop(); |
|
|
|
ws.send(answerQuery); |
|
|
|
break; |
|
|
|
case CHOOSE_QUESTION: |
|
|
|
question = result.parameters.fields.num.numberValue; |
|
|
|
state = 'answer'; |
|
|
|
handleQuestion(); |
|
|
|
startQuestion(question); |
|
|
|
break; |
|
|
|
case FALLBACK_INTENT: |
|
|
|
// if (state === 'answer') { |
|
|
|
// handleAnswer(result.queryText) |
|
|
|
// } |
|
|
|
// fallback what should happen if no intent is detected |
|
|
|
// this is handled in the processSpeech() function |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
@@ -217,6 +214,7 @@ function checkIntent (result) { |
|
|
|
function startQuestion (number) { |
|
|
|
question = number; |
|
|
|
state = 'answer'; |
|
|
|
answerQuery = ''; |
|
|
|
questionNumDisplay.textContent = 'Question: ' + question; |
|
|
|
handleQuestion(); |
|
|
|
} |
|
|
@@ -224,9 +222,7 @@ function startQuestion (number) { |
|
|
|
function handleQuestion () { |
|
|
|
switch (question) { |
|
|
|
case 1: |
|
|
|
skipRecording = true; |
|
|
|
speak(QUESTION_ONE); |
|
|
|
readQuestionOne(); |
|
|
|
readQuestionOne(QUESTION_ONE); |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
readQuestionTwo(); |
|
|
@@ -238,11 +234,14 @@ function handleQuestion () { |
|
|
|
readQuestionFour(); |
|
|
|
break; |
|
|
|
case 5: |
|
|
|
proceedWithRecording = true; |
|
|
|
speak(QUESTION_FIVE); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function readQuestionOne () { |
|
|
|
function readQuestionOne (questionText) { |
|
|
|
speak(questionText); |
|
|
|
for (let i = 0; i < QUESTION_ONE_QUESTIONS.length; i++) { |
|
|
|
let utterance = new SpeechSynthesisUtterance(); |
|
|
|
utterance.voice = voices[2]; |
|
|
@@ -280,7 +279,6 @@ function readQuestionTwo () { |
|
|
|
} |
|
|
|
|
|
|
|
function readQuestionThree () { |
|
|
|
skipRecording = true; |
|
|
|
speak('Dankeschön, weiter geht es mit der nächsten Frage.'); |
|
|
|
let utterance = new SpeechSynthesisUtterance(); |
|
|
|
utterance.voice = voices[2]; |
|
|
@@ -288,13 +286,13 @@ function readQuestionThree () { |
|
|
|
utterance.rate = 0.88; |
|
|
|
window.speechSynthesis.speak(utterance); |
|
|
|
utterance.onend = function (event) { |
|
|
|
proceedWithRecording = true; |
|
|
|
speak(QUESTION_THREE_QUESTIONS_PT1[questionThreeCount]); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
function readQuestionFour () { |
|
|
|
// skipRecording = true; |
|
|
|
// speak(QUESTION_FOUR); |
|
|
|
speak(QUESTION_FOUR); |
|
|
|
for (let i = 0; i < QUESTION_FOUR_PT2.length; i++) { |
|
|
|
let utterance = new SpeechSynthesisUtterance(); |
|
|
|
utterance.voice = voices[2]; |
|
|
@@ -302,7 +300,7 @@ function readQuestionFour () { |
|
|
|
utterance.text = QUESTION_FOUR_PT2[i]; |
|
|
|
window.speechSynthesis.speak(utterance); |
|
|
|
} |
|
|
|
// speak('Sie haben hierfür 1 Minute Zeit.'); |
|
|
|
speak('Sie haben hierfür 1 Minute Zeit.'); |
|
|
|
} |
|
|
|
|
|
|
|
function handleAnswer (query) { |
|
|
@@ -317,37 +315,33 @@ function handleAnswer (query) { |
|
|
|
handleAnswerToThirdQuestion(query); |
|
|
|
break; |
|
|
|
case 4: |
|
|
|
// not possible with the current state of web speech api |
|
|
|
// handleAnswerToFourthQuestion(query); |
|
|
|
break; |
|
|
|
case 5: |
|
|
|
handleAnswerToFifthQuestion(query); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function handleAnswerToFirstQuestion (answer) { |
|
|
|
var tokens = answer.split(new RegExp(separators.join('|'), 'g')); |
|
|
|
questionPoints[question] += calculatePoints(tokens, QUESTION_ONE_ANSWERS); |
|
|
|
deconstructAndCalculateAnswer(answer); |
|
|
|
if (partTwo) { |
|
|
|
partTwo = false; |
|
|
|
console.log('question 1 points: ' + questionPoints[question]); |
|
|
|
skipRecording = true; |
|
|
|
speak('Vielen Dank, nun geht es weiter mit der nächsten Frage'); |
|
|
|
startQuestion(2); |
|
|
|
// state = 'detect' |
|
|
|
} else { |
|
|
|
rePrompt = false; |
|
|
|
skipRecording = true; |
|
|
|
// currently disabled feature |
|
|
|
// rePrompt = false; |
|
|
|
speak(QUESTION_ONE_PT2); |
|
|
|
readQuestionOne(QUESTION_ONE); |
|
|
|
readQuestionOne(QUESTION_ONE_PT2); |
|
|
|
partTwo = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function handleAnswerToSecondQuestion (answer) { |
|
|
|
var tokens = answer.split(new RegExp(separators.join('|'), 'g')); |
|
|
|
questionPoints[question] = calculatePoints(tokens, QUESTION_TWO_ANSWERS); |
|
|
|
console.log('question 2 points: ' + questionPoints[question]); |
|
|
|
deconstructAndCalculateAnswer(answer); |
|
|
|
startQuestion(3); |
|
|
|
// state = 'detect' |
|
|
|
} |
|
|
|
|
|
|
|
function handleAnswerToThirdQuestion (query) { |
|
|
@@ -376,41 +370,58 @@ function handleAnswerToThirdQuestion (query) { |
|
|
|
if (strike === 2 || questionThreeCount === 5) { |
|
|
|
speechsynth.rate = 0.88; |
|
|
|
console.log('question 3 points: ' + questionPoints[question]); |
|
|
|
skipRecording = true; |
|
|
|
speak('weiter geht es mit der Nächsten Frage'); |
|
|
|
startQuestion(4); |
|
|
|
// Question 4 is not possible to take, because of technical limitation |
|
|
|
// startQuestion(4); |
|
|
|
|
|
|
|
startQuestion(5); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
proceedWithRecording = true; |
|
|
|
speak(questionArray[questionThreeCount]); |
|
|
|
|
|
|
|
console.log('count: ' + questionThreeCount + ', strike: ' + strike + ', points: ' + questionPoints[question]); |
|
|
|
} |
|
|
|
|
|
|
|
// not possible with the current state of web speech api |
|
|
|
// function handleAnswerToFourthQuestion (answer) { |
|
|
|
// // In order to evaluate the answer, the recognizer has to distinguish between the number 77 spoken "seventy seven" and 7-7 spoken "seven seven", which it doesnt |
|
|
|
// startQuestion(5); |
|
|
|
// } |
|
|
|
|
|
|
|
function handleAnswerToFifthQuestion (answer) { |
|
|
|
deconstructAndCalculateAnswer(answer); |
|
|
|
speak(FINISH); |
|
|
|
} |
|
|
|
|
|
|
|
// #endregion |
|
|
|
|
|
|
|
// NOT SUPPORTED |
|
|
|
// function recognizeSpeech () { |
|
|
|
// if (state === 'answer') { |
|
|
|
// var arr; |
|
|
|
// switch (question) { |
|
|
|
// case 1: |
|
|
|
// arr = QUESTION_ONE_QUESTIONS; |
|
|
|
// break; |
|
|
|
// case 2: |
|
|
|
// // arr = QUESTION_TWO_QUESTIONS; |
|
|
|
// arr = QUESTION_TWO_QUESTIONS; |
|
|
|
// break; |
|
|
|
// case 3: |
|
|
|
// arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; |
|
|
|
// break; |
|
|
|
// case 4: |
|
|
|
// arr = ['eins', 'zwei', 'drei', 'vier', 'fünf', 'sechs', 'sieben', 'acht', 'neun']; |
|
|
|
// break; |
|
|
|
// case 5: |
|
|
|
// break; |
|
|
|
// } |
|
|
|
|
|
|
|
// // var grammar = '#JSGF V1.0; grammar colors; public <color> = ' + arr.join(' | ') + ' ;'; |
|
|
|
// // var speechRecognitionList = new SpeechGrammarList(); |
|
|
|
// // speechRecognitionList.addFromString(grammar, 1); |
|
|
|
// // recognition.grammars = speechRecognitionList; |
|
|
|
// var grammar = '#JSGF V1.0; grammar arr; public <arr> = ' + arr.join(' | ') + ' ;'; |
|
|
|
// var speechRecognitionList = new SpeechGrammarList(); |
|
|
|
// speechRecognitionList.addFromString(grammar, 1); |
|
|
|
// recognition.grammars = speechRecognitionList; |
|
|
|
|
|
|
|
// recognition.start(); |
|
|
|
// } |
|
|
|
|
|
|
|
// #region speech recognition event |
|
|
@@ -506,18 +517,16 @@ function processSpeech (speechResult) { |
|
|
|
} |
|
|
|
|
|
|
|
if (state === 'answer') { |
|
|
|
if (timerId != undefined) { |
|
|
|
clearTimeout(timerId); |
|
|
|
} |
|
|
|
stopRecognitionFallback(); |
|
|
|
answerQuery += speechResult; |
|
|
|
timerId = window.setTimeout( |
|
|
|
function () { |
|
|
|
// currently disabled |
|
|
|
// if (!rePrompt) { |
|
|
|
// ws.send('ich brauche noch etwas Zeit') |
|
|
|
// } else { |
|
|
|
console.log('recording end. Evaluate: ' + answerQuery); |
|
|
|
handleAnswer(answerQuery); |
|
|
|
answerQuery = ''; |
|
|
|
diagnosticPara.textContent = ''; |
|
|
|
// } |
|
|
|
recognition.stop(); |
|
|
@@ -539,14 +548,7 @@ function startDemenzScreening () { |
|
|
|
} |
|
|
|
|
|
|
|
function testSpeechOut () { |
|
|
|
readQuestionFour(); |
|
|
|
|
|
|
|
// speechsynth.text = 'test 123'; |
|
|
|
// speechsynth.volume = 1; |
|
|
|
// speechsynth.rate = 1; |
|
|
|
// console.log(speechsynth); |
|
|
|
// window.speechSynthesis.speak(speechsynth); |
|
|
|
// console.log(window.speechSynthesis); |
|
|
|
question = 4; |
|
|
|
} |
|
|
|
|
|
|
|
function speak (sentence) { |
|
|
@@ -554,6 +556,29 @@ function speak (sentence) { |
|
|
|
window.speechSynthesis.speak(speechsynth); |
|
|
|
} |
|
|
|
|
|
|
|
function stopRecognitionFallback () { |
|
|
|
if (timerId != undefined) { |
|
|
|
clearTimeout(timerId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function deconstructAndCalculateAnswer (answer) { |
|
|
|
let questionAnswers; |
|
|
|
switch (question) { |
|
|
|
case 1: |
|
|
|
questionAnswers = QUESTION_ONE_ANSWERS; |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
questionAnswers = QUESTION_TWO_ANSWERS; |
|
|
|
break; |
|
|
|
case 5: |
|
|
|
questionAnswers = QUESTION_ONE_ANSWERS; |
|
|
|
break; |
|
|
|
} |
|
|
|
var tokens = answer.split(new RegExp(separators.join('|'), 'g')); |
|
|
|
questionPoints[question] += calculatePoints(tokens, questionAnswers); |
|
|
|
} |
|
|
|
|
|
|
|
function calculatePoints (tokens, d) { |
|
|
|
let points = 0; |
|
|
|
let dict = {}; |