You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ws-client.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // web speech recognition api
  2. var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
  3. var SpeechGrammarList = SpeechGrammarList || webkitSpeechGrammarList;
  4. var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent;
  5. // state management
  6. var state = '';
  7. var question = 0;
  8. var rePrompt = false;
  9. var partTwo = false;
  10. var count = 0;
  11. var strike = 0;
  12. // Questions
  13. const QUESTION_ONE = 'Ich werde Ihnen jetzt langsam eine Liste mit Worten vorlesen. Danach wiederholen Sie bitte möglichst viele dieser Worte. Auf die Reihenfolge kommt es nicht an.';
  14. const QUESTION_ONE_PT2 = 'Vielen Dank. Nun nenne ich Ihnen die gleichen 10 Worte ein zweites mal. Auch danach sollen Sie wieder möglichst viele Worte wiederholen';
  15. const QUESTION_TWO = 'Nennen Sie mir bitte so viel Dinge wie möglich, die man im Supermarkt kaufen kann. Sie haben dafür eine Minute Zeit.';
  16. 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.';
  17. // intents
  18. const WELCOME_INTENT = 'Default Welcome Intent';
  19. const WELCOME_FOLLOWUP_YES = 'Default Welcome Intent - yes';
  20. const WELCOME_FOLLOWUP_NO = 'Default Welcome Intent - no';
  21. const MORE_TIME = 'Add Time Intent';
  22. const MORE_TIME_YES = 'Add Time Intent - yes';
  23. const MORE_TIME_NO = 'Add Time Intent - no';
  24. const QUIT_INTENT = 'Quit Intent';
  25. const FALLBACK_INTENT = 'Default Fallback Intent';
  26. const HELP_INTENT = 'Help Intent';
  27. const CHOOSE_QUESTION = 'Frage_Starten';
  28. const NEXT_QUESTION = 'Nächste Frage';
  29. // question one results
  30. const QUESTION_ONE_ANSWERS = ['teller', 'hund', 'lampe', 'brief', 'apfel', 'apfelwiese', 'apfelwiese', 'apfelbaum', 'apfelbaum', 'und', 'hose', 'tisch', 'wiese', 'glas', 'baum'];
  31. const QUESTION_ONE_QUESTIONS = ['teller', 'hund', 'lampe', 'brief', 'apfel', 'hose', 'tisch', 'wiese', 'glas', 'baum'];
  32. const QUESTION_TWO_ANSWERS = [''];
  33. const QUESTION_TWO_QUESTIONS = [''];
  34. const QUESTION_THREE_QUESTIONS_PT1 = ['7, 2', '4, 7, 9', '5, 4, 9, 6', '2, 7, 5, 3, 6', '8, 1, 3, 5, 4, 2'];
  35. const QUESTION_THREE_QUESTIONS_PT2 = ['8, 6', '3, 1, 5', '1, 9, 7, 4', '1, 3, 5, 4, 8', '4, 1, 2, 7, 9, 5'];
  36. const QUESTION_THREE_ANSWERS_PT1 = ['27', '974', '6945', '63572', '245318'];
  37. const QUESTION_THREE_ANSWERS_PT2 = ['68', '513', '4791', '84531', '597214'];
  38. // points
  39. var questionOnePoints = 0;
  40. var questionTwoPoints = 0;
  41. var questionThreePoints = 0;
  42. var questionFourPoints = 0;
  43. var questionFivePoints = 0;
  44. var questionSixPoints = 0;
  45. // tokenization
  46. const separators = [' ', '\\\+', '-', '\\\(', '\\\)', '\\*', '/', ':', '\\\?'];
  47. // Timers
  48. var timerId;
  49. // html elements
  50. var serverPara = document.querySelector('.server');
  51. var diagnosticPara = document.querySelector('.output');
  52. var testBtn = document.querySelector('button');
  53. var testBtn2 = document.getElementById('speechBtn');
  54. var infoPara = document.getElementById('info');
  55. var userPrompt = document.getElementById('query');
  56. console.log(window.location.host + window.location.pathname);
  57. // websocket to communicate with the server
  58. var ws = new WebSocket('ws://localhost:8000/ws');
  59. // speech recognition
  60. var recognition = new SpeechRecognition();
  61. recognition.lang = 'de-DE';
  62. // recognition.interimResults = false;
  63. recognition.maxAlternatives = 1;
  64. recognition.continuous = true;
  65. var answerQuery = '';
  66. var skipRecording = false;
  67. // speech synthesis
  68. var speechsynth = new SpeechSynthesisUtterance();
  69. var listSpeechsynth = new SpeechSynthesisUtterance();
  70. var voices;
  71. window.speechSynthesis.onvoiceschanged = function () {
  72. voices = window.speechSynthesis.getVoices();
  73. voices.forEach(element => {
  74. if (element.name === 'Google Deutsch') {
  75. speechsynth.voice = element;
  76. listSpeechsynth.voice = element;
  77. }
  78. });
  79. listSpeechsynth.rate = 0.7;
  80. };
  81. function startDemenzScreening () {
  82. console.log('button clicked');
  83. ws.send('starte demenz test');
  84. //
  85. // state = 'answer'
  86. // recognizeSpeech()
  87. //
  88. testBtn.disabled = true;
  89. testBtn.textContent = 'Test in progress';
  90. infoPara.textContent = 'wait...';
  91. }
  92. function speak (sentence) {
  93. speechsynth.text = sentence;
  94. window.speechSynthesis.speak(speechsynth);
  95. }
  96. function testSpeechOut () {
  97. console.log('click');
  98. // skipRecording = true
  99. // let utterance = new SpeechSynthesisUtterance()
  100. // utterance.voice = voices[2]
  101. // // utterance.rate = 0.75
  102. // utterance.text = QUESTION_THREE
  103. // window.speechSynthesis.speak(utterance)
  104. //
  105. // question = 3;
  106. // startQuestion(question);
  107. // state = 'answer';
  108. speechsynth.text = 'test 123';
  109. speechsynth.volume = 1;
  110. speechsynth.rate = 1;
  111. console.log(speechsynth);
  112. window.speechSynthesis.speak(speechsynth);
  113. console.log(window.speechSynthesis);
  114. // speak('Niko ist der größte hurn eu west');
  115. }
  116. // websocket events
  117. ws.onopen = function () {
  118. serverPara.style.background = 'green';
  119. serverPara.innerHTML = 'Server online';
  120. };
  121. ws.onmessage = function (payload) {
  122. var dialogflowResult = JSON.parse(payload.data);
  123. checkIntent(dialogflowResult);
  124. document.querySelector('h1').innerHTML = dialogflowResult.intent.displayName;
  125. };
  126. // INTENT HANDLING
  127. function checkIntent (result) {
  128. switch (result.intent.displayName) {
  129. case QUIT_INTENT:
  130. state = 'quit';
  131. skipRecording = true;
  132. speak('Okay, Danke fürs Benutzen.');
  133. break;
  134. case WELCOME_INTENT:
  135. state = 'detect';
  136. // speak(result.fulfillmentText)
  137. speak('go?');
  138. break;
  139. case WELCOME_FOLLOWUP_YES:
  140. startQuestion(1);
  141. break;
  142. case WELCOME_FOLLOWUP_NO:
  143. skipRecording = true;
  144. speak('Okay, Danke fürs Benutzen.');
  145. break;
  146. case MORE_TIME:
  147. state = 'detect';
  148. speak('Brauchen Sie noch etwas Zeit?');
  149. break;
  150. case MORE_TIME_YES:
  151. rePrompt = true;
  152. state = 'answer';
  153. speak('Alles klar');
  154. break;
  155. case MORE_TIME_NO:
  156. skipRecording = true;
  157. state = 'answer';
  158. speak('Verstanden');
  159. recognition.stop();
  160. ws.send(answerQuery);
  161. break;
  162. case CHOOSE_QUESTION:
  163. question = result.parameters.fields.num.numberValue;
  164. state = 'answer';
  165. handleQuestion();
  166. break;
  167. case FALLBACK_INTENT:
  168. // if (state === 'answer') {
  169. // handleAnswer(result.queryText)
  170. // }
  171. break;
  172. default:
  173. break;
  174. }
  175. }
  176. function startQuestion (number) {
  177. question = number;
  178. state = 'answer';
  179. handleQuestion();
  180. }
  181. // QUESTION HANDLING
  182. function handleQuestion () {
  183. switch (question) {
  184. case 1:
  185. readQuestionOne(QUESTION_ONE);
  186. break;
  187. case 2:
  188. readQuestionTwo(QUESTION_TWO);
  189. break;
  190. case 3:
  191. // skipRecording = true;
  192. // speak(QUESTION_THREE);
  193. speak(QUESTION_THREE_QUESTIONS_PT1[0]);
  194. break;
  195. case 4:
  196. break;
  197. case 5:
  198. break;
  199. }
  200. }
  201. function handleAnswer (query) {
  202. switch (question) {
  203. case 1:
  204. handleAnswerToFirstQuestion(query);
  205. break;
  206. case 2:
  207. handleAnswerToSecondQuestion(query);
  208. break;
  209. case 3:
  210. handleAnswerToThirdQuestion(query);
  211. break;
  212. case 4:
  213. break;
  214. case 5:
  215. break;
  216. }
  217. }
  218. function handleAnswerToFirstQuestion (answer) {
  219. var tokens = answer.split(new RegExp(separators.join('|'), 'g'));
  220. questionOnePoints = calculatePoints(tokens, QUESTION_ONE_ANSWERS);
  221. if (partTwo) {
  222. partTwo = false;
  223. startQuestion(2);
  224. // state = 'detect'
  225. } else {
  226. rePrompt = false;
  227. speak(QUESTION_ONE_PT2);
  228. partTwo = true;
  229. }
  230. }
  231. function handleAnswerToSecondQuestion (answer) {
  232. var tokens = answer.split(new RegExp(separators.join('|'), 'g'));
  233. questionTwoPoints = calculatePoints(tokens, QUESTION_TWO_ANSWERS);
  234. skipRecording = true;
  235. speak('Sie haben ' + questionOnePoints + 'Punkte');
  236. startQuestion(3);
  237. // state = 'detect'
  238. }
  239. function handleAnswerToThirdQuestion (query) {
  240. speechsynth.rate = 0.87;
  241. query = query.replace(' ', '');
  242. let answerArray;
  243. let questionArray;
  244. if (!partTwo) {
  245. answerArray = QUESTION_THREE_ANSWERS_PT1;
  246. } else {
  247. answerArray = QUESTION_THREE_ANSWERS_PT2;
  248. }
  249. if (query === answerArray[count]) {
  250. strike = 0;
  251. partTwo = false;
  252. count++;
  253. questionThreePoints = count + 1;
  254. questionArray = QUESTION_THREE_QUESTIONS_PT1;
  255. } else {
  256. strike++;
  257. partTwo = true;
  258. questionArray = QUESTION_THREE_QUESTIONS_PT2;
  259. }
  260. if (strike === 2 || count === 5) {
  261. speechsynth.rate = 1;
  262. skipRecording = true;
  263. speak('weiter geht es mit der Nächsten Frage');
  264. startQuestion(4);
  265. return;
  266. }
  267. speak(questionArray[count]);
  268. console.log('count: ' + count + ', strike: ' + strike + ', points: ' + questionThreePoints);
  269. }
  270. // Question specific functions
  271. function readQuestionOne (text) {
  272. skipRecording = true;
  273. speak(text);
  274. for (let i = 0; i < QUESTION_ONE_QUESTIONS.length; i++) {
  275. let utterance = new SpeechSynthesisUtterance();
  276. utterance.voice = voices[2];
  277. utterance.rate = 0.75;
  278. utterance.text = QUESTION_ONE_QUESTIONS[i];
  279. window.speechSynthesis.speak(utterance);
  280. if (i === 9) {
  281. utterance.onend = function (event) {
  282. console.log('end of aufzählung' + i);
  283. recognizeSpeech();
  284. };
  285. }
  286. }
  287. }
  288. function readQuestionTwo (text) {
  289. let utterance = new SpeechSynthesisUtterance();
  290. utterance.voice = voices[2];
  291. utterance.text = text;
  292. window.speechSynthesis.speak(utterance);
  293. console.log('q 2 started');
  294. utterance.onend = function (event) {
  295. window.setTimeout(
  296. function () {
  297. recognition.stop();
  298. handleAnswer(answerQuery);
  299. }, 60000);
  300. console.log('q 2 recognition started');
  301. recognizeSpeech();
  302. };
  303. }
  304. function calculatePoints (tokens, array) {
  305. let points = 0;
  306. for (let i of array) {
  307. for (let j of tokens) {
  308. if (i === j) {
  309. points++;
  310. }
  311. }
  312. }
  313. return points;
  314. }
  315. speechsynth.onend = function (event) {
  316. switch (question) {
  317. case 1:
  318. break;
  319. case 2:
  320. break;
  321. case 3:
  322. break;
  323. case 4:
  324. break;
  325. case 5:
  326. break;
  327. }
  328. if (!skipRecording) {
  329. recognizeSpeech();
  330. }
  331. skipRecording = false;
  332. console.log('global speech end');
  333. };
  334. function recognizeSpeech () {
  335. if (state === 'answer') {
  336. var arr;
  337. switch (question) {
  338. case 1:
  339. arr = QUESTION_ONE_QUESTIONS;
  340. break;
  341. case 2:
  342. return;
  343. case 3:
  344. arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  345. break;
  346. case 4:
  347. break;
  348. case 5:
  349. break;
  350. }
  351. var grammar = '#JSGF V1.0; grammar colors; public <color> = ' + arr.join(' | ') + ' ;';
  352. var speechRecognitionList = new SpeechGrammarList();
  353. speechRecognitionList.addFromString(grammar, 1);
  354. recognition.grammars = speechRecognitionList;
  355. }
  356. recognition.start();
  357. console.log('reocgnition started');
  358. recognition.onresult = function (event) {
  359. var last = event.results.length - 1;
  360. var speechResult = event.results[last][0].transcript.toLowerCase();
  361. diagnosticPara.textContent += speechResult + ' ';
  362. // console.log('Confidence: ' + event.results[0][0].confidence)
  363. processSpeech(speechResult);
  364. // testBtn.disabled = false
  365. // testBtn.textContent = 'record...'
  366. };
  367. function processSpeech (speechResult) {
  368. console.log('To dialogflow: ' + speechResult);
  369. ws.send(speechResult);
  370. let timeOut;
  371. switch (question) {
  372. case 1:
  373. timeOut = 6500;
  374. break;
  375. case 2:
  376. answerQuery += speechResult;
  377. return;
  378. case 3:
  379. if (speechResult.includes('uhr')) {
  380. speechResult = speechResult.replace('uhr', '');
  381. }
  382. timeOut = 6500;
  383. break;
  384. case 4:
  385. break;
  386. case 5:
  387. break;
  388. }
  389. if (state === 'answer') {
  390. if (timerId != undefined) {
  391. clearTimeout(timerId);
  392. }
  393. answerQuery += speechResult;
  394. timerId = window.setTimeout(
  395. function () {
  396. // if (!rePrompt) {
  397. // ws.send('ich brauche noch etwas Zeit')
  398. // } else {
  399. console.log('recording end. Evaluate: ' + answerQuery);
  400. handleAnswer(answerQuery);
  401. answerQuery = '';
  402. diagnosticPara.textContent = '';
  403. // }
  404. recognition.stop();
  405. console.log('timer fallback');
  406. }, timeOut);
  407. } else {
  408. console.log('recording end.');
  409. recognition.stop();
  410. }
  411. }
  412. recognition.onspeechend = function () {
  413. // recognition.stop();
  414. // testBtn.disabled = false;
  415. // testBtn.textContent = 'Start new test';
  416. };
  417. recognition.onerror = function (event) {
  418. testBtn.disabled = false;
  419. testBtn.textContent = 'Start new test';
  420. diagnosticPara.textContent = 'Error occurred in recognition: ' + event.error;
  421. };
  422. recognition.onaudiostart = function (event) {
  423. // Fired when the user agent has started to capture audio.
  424. };
  425. recognition.onaudioend = function (event) {
  426. };
  427. recognition.onend = function (event) {
  428. // Fired when the speech recognition service has disconnected.
  429. };
  430. recognition.onnomatch = function (event) {
  431. // Fired when the speech recognition service returns a final result with no significant recognition. This may involve some degree of recognition, which doesn't meet or exceed the confidence threshold.
  432. // console.log('SpeechRecognition.onnomatch')
  433. };
  434. recognition.onsoundstart = function (event) {
  435. // Fired when any sound — recognisable speech or not — has been detected.
  436. };
  437. recognition.onsoundend = function (event) {
  438. // Fired when any sound — recognisable speech or not — has stopped being detected.
  439. };
  440. recognition.onspeechstart = function (event) {
  441. // Fired when sound that is recognised by the speech recognition service as speech has been detected.
  442. };
  443. recognition.onstart = function (event) {
  444. // Fired when the speech recognition service has begun listening to incoming audio with intent to recognize grammars associated with the current SpeechRecognition.
  445. };
  446. }
  447. testBtn.addEventListener('click', startDemenzScreening);
  448. testBtn2.addEventListener('click', testSpeechOut);