Libraryless. Click here for Pure Java version (2708L/22K/69K).
1 | !752 |
2 | |
3 | !include #1002943 // Pivo Logic (include) |
4 | |
5 | static S logName = "log"; |
6 | static long requestID, logLength; |
7 | |
8 | static L<S> showableFiles = litlist(logName); // ... |
9 | |
10 | static new L<Entry> history; |
11 | |
12 | static class Entry { |
13 | long time; |
14 | S cookie; |
15 | S userSaid, botSaid; |
16 | long logID; |
17 | } |
18 | |
19 | static new L<Bot> bots; |
20 | |
21 | static class Bot { |
22 | // n = where new stuff starts |
23 | void learnFrom(L<Entry> history, int n) {} |
24 | |
25 | S answer(S question) { ret null; } |
26 | |
27 | void load(LoadEnv env) {} |
28 | void save(LoadEnv env) {} |
29 | } |
30 | |
31 | p { |
32 | pivoLoad(); |
33 | load("requestID"); |
34 | L<Map> log = scanMapLog(logName); |
35 | logLength += l(log); |
36 | addToHistory(makeHistory(log)); |
37 | } |
38 | |
39 | static S rawLink(S pageName) { |
40 | ret "/" + parseSnippetID(getProgramID()) + "/raw/" + pageName; |
41 | } |
42 | |
43 | static long newRequestID() { |
44 | long id = ++requestID; |
45 | save("requestID"); |
46 | ret id; |
47 | } |
48 | |
49 | static S html(S uri, Map<S, S> params) { |
50 | if (eq(uri, "/log")) |
51 | ret htable(scanMapLog(logName)); |
52 | if (eq(uri, "/has-speech")) { |
53 | O cookieHandler = call(getMainBot(), "getCookies"); |
54 | S cookieMD5 = md5((S) call(cookieHandler, "read", "cookie")); |
55 | |
56 | S language = getString(params, "language"); |
57 | long requestID = newRequestID(); |
58 | S s = params.get("q"); |
59 | Map logData = litmap("ip", getClientIP(), "thread", threadID(), "cookie", cookieMD5, "language", language, "heard", s); |
60 | log(mapPlus(logData, "starting", now())); |
61 | |
62 | ((ThreadLocal<Boolean>) get(getMainBot(), "attn")).set(true); |
63 | pivoMode.set(true); |
64 | S text = //askSelf(s); |
65 | callStaticAnswerMethod(mc(), s); |
66 | if (empty(text)) { |
67 | log(mapPlus(logData, "done", now(), "saying", "-")); |
68 | ret ""; |
69 | } |
70 | |
71 | S voice = eq(language, "6") ? "William" : "Alex"; |
72 | S soundURL = getSoundURLCereproc(text, voice); |
73 | S html = [[ |
74 | <audio controls autoplay> |
75 | <source src="SRC" type="audio/mpeg"> |
76 | ! Kein Ton im Browser ! |
77 | </audio> |
78 | ]]; |
79 | html = html.replace("SRC", htmlencode(soundURL)); |
80 | log(mapPlus(logData, "done", now(), "saying", text)); |
81 | ret "Speech (" + voice + "): " + htmlencode(text) + "<br>" + html; |
82 | } |
83 | |
84 | if (eq(uri, "/empty")) { |
85 | ret ""; |
86 | } |
87 | |
88 | if (eq(uri, "/upper")) { |
89 | S html = [=[ |
90 | <!DOCTYPE html> |
91 | <meta charset="utf-8"> |
92 | <title>TinyBrain Speech Demo</title> |
93 | <style> |
94 | * { |
95 | font-family: Verdana, Arial, sans-serif; |
96 | } |
97 | a:link { |
98 | color:#000; |
99 | text-decoration: none; |
100 | } |
101 | a:visited { |
102 | color:#000; |
103 | } |
104 | a:hover { |
105 | color:#33F; |
106 | } |
107 | .button { |
108 | background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%); |
109 | border: 1px solid #076bd2; |
110 | border-radius: 3px; |
111 | color: #fff; |
112 | display: none; |
113 | font-size: 13px; |
114 | font-weight: bold; |
115 | line-height: 1.3; |
116 | padding: 8px 25px; |
117 | text-align: center; |
118 | text-shadow: 1px 1px 1px #076bd2; |
119 | letter-spacing: normal; |
120 | } |
121 | .center { |
122 | padding: 10px; |
123 | text-align: center; |
124 | } |
125 | .final { |
126 | color: black; |
127 | padding-right: 3px; |
128 | } |
129 | .interim { |
130 | color: gray; |
131 | } |
132 | .info { |
133 | font-size: 34px; |
134 | text-align: center; |
135 | color: #777; |
136 | display: none; |
137 | } |
138 | .right { |
139 | float: right; |
140 | } |
141 | .sidebyside { |
142 | display: inline-block; |
143 | width: 45%; |
144 | min-height: 40px; |
145 | text-align: left; |
146 | vertical-align: top; |
147 | } |
148 | #headline { |
149 | font-size: 80px; |
150 | font-weight: 300; |
151 | } |
152 | #info { |
153 | font-size: 50px; |
154 | text-align: center; |
155 | color: #777; |
156 | visibility: hidden; |
157 | } |
158 | #results { |
159 | font-size: 55px; |
160 | font-weight: bold; |
161 | border: 1px solid #ddd; |
162 | padding: 15px; |
163 | text-align: left; |
164 | min-height: 50px; |
165 | } |
166 | #start_button { |
167 | border: 0; background-color:transparent; |
168 | padding: 0; |
169 | } |
170 | </style> |
171 | |
172 | <div id="info"> |
173 | <p id="info_start">Click on the microphone icon and begin speaking.</p> |
174 | <p id="info_speak_now">Speak after the bleep.</p> |
175 | <p id="info_no_speech">No speech was detected</p> |
176 | <p id="info_no_microphone" style="display:none"> |
177 | No microphone was found. Ensure that a microphone is installed and that |
178 | <a href="//support.google.com/chrome/bin/answer.py?hl=en&answer=1407892"> |
179 | microphone settings</a> are configured correctly.</p> |
180 | <p id="info_allow">Click the "Allow" button.</p> |
181 | <p id="info_denied">Permission to use microphone was denied.</p> |
182 | <p id="info_blocked">Permission to use microphone is blocked. To change, |
183 | go to chrome://settings/contentExceptions#media-stream</p> |
184 | <p id="info_upgrade">Web Speech API is not supported by this browser. |
185 | Upgrade to <a href="//www.google.com/chrome">Chrome</a> |
186 | version 25 or later.</p> |
187 | </div> |
188 | <div class="right"> |
189 | <button id="start_button" onclick="startButton(event)"> |
190 | <img id="start_img" src="http://tinybrain.de:8080/speech/mic.gif" width="120" alt="Start"></button> |
191 | </div> |
192 | <div id="results"> |
193 | <span id="final_span" class="final"></span> |
194 | <span id="interim_span" class="interim"></span> |
195 | <p> |
196 | </div> |
197 | <div class="center"> |
198 | <p> |
199 | <div id="div_language"> |
200 | <?= $mode ?> |
201 | |
202 | <select style="font-size: 30px" id="select_language" onchange="updateCountry()"></select> |
203 | |
204 | <select id="select_dialect"></select> |
205 | </div> |
206 | </div> |
207 | <script> |
208 | var langs = |
209 | [['Afrikaans', ['af-ZA']], |
210 | ['Bahasa Indonesia',['id-ID']], |
211 | ['Bahasa Melayu', ['ms-MY']], |
212 | ['Català', ['ca-ES']], |
213 | ['?eština', ['cs-CZ']], |
214 | ['Deutsch', ['de-DE']], |
215 | ['English', ['en-AU', 'Australia'], |
216 | ['en-CA', 'Canada'], |
217 | ['en-IN', 'India'], |
218 | ['en-NZ', 'New Zealand'], |
219 | ['en-ZA', 'South Africa'], |
220 | ['en-GB', 'United Kingdom'], |
221 | ['en-US', 'United States']], |
222 | ['Español', ['es-AR', 'Argentina'], |
223 | ['es-BO', 'Bolivia'], |
224 | ['es-CL', 'Chile'], |
225 | ['es-CO', 'Colombia'], |
226 | ['es-CR', 'Costa Rica'], |
227 | ['es-EC', 'Ecuador'], |
228 | ['es-SV', 'El Salvador'], |
229 | ['es-ES', 'España'], |
230 | ['es-US', 'Estados Unidos'], |
231 | ['es-GT', 'Guatemala'], |
232 | ['es-HN', 'Honduras'], |
233 | ['es-MX', 'México'], |
234 | ['es-NI', 'Nicaragua'], |
235 | ['es-PA', 'Panamá'], |
236 | ['es-PY', 'Paraguay'], |
237 | ['es-PE', 'Perú'], |
238 | ['es-PR', 'Puerto Rico'], |
239 | ['es-DO', 'República Dominicana'], |
240 | ['es-UY', 'Uruguay'], |
241 | ['es-VE', 'Venezuela']], |
242 | ['Euskara', ['eu-ES']], |
243 | ['Français', ['fr-FR']], |
244 | ['Galego', ['gl-ES']], |
245 | ['Hrvatski', ['hr_HR']], |
246 | ['IsiZulu', ['zu-ZA']], |
247 | ['Íslenska', ['is-IS']], |
248 | ['Italiano', ['it-IT', 'Italia'], |
249 | ['it-CH', 'Svizzera']], |
250 | ['Magyar', ['hu-HU']], |
251 | ['Nederlands', ['nl-NL']], |
252 | ['Norsk bokmål', ['nb-NO']], |
253 | ['Polski', ['pl-PL']], |
254 | ['Português', ['pt-BR', 'Brasil'], |
255 | ['pt-PT', 'Portugal']], |
256 | ['Român?', ['ro-RO']], |
257 | ['Sloven?ina', ['sk-SK']], |
258 | ['Suomi', ['fi-FI']], |
259 | ['Svenska', ['sv-SE']], |
260 | ['Türkçe', ['tr-TR']], |
261 | ['?????????', ['bg-BG']], |
262 | ['P??????', ['ru-RU']], |
263 | ['??????', ['sr-RS']], |
264 | ['???', ['ko-KR']], |
265 | ['??', ['cmn-Hans-CN', '??? (????)'], |
266 | ['cmn-Hans-HK', '??? (??)'], |
267 | ['cmn-Hant-TW', '?? (??)'], |
268 | ['yue-Hant-HK', '?? (??)']], |
269 | ['???', ['ja-JP']], |
270 | ['Lingua lat?na', ['la']]]; |
271 | |
272 | for (var i = 0; i < langs.length; i++) { |
273 | select_language.options[i] = new Option(langs[i][0], i); |
274 | } |
275 | |
276 | // 6 = English |
277 | |
278 | select_language.selectedIndex = 6; |
279 | updateCountry(); |
280 | select_dialect.selectedIndex = 6; |
281 | showInfo('info_start'); |
282 | |
283 | function updateCountry() { |
284 | for (var i = select_dialect.options.length - 1; i >= 0; i--) { |
285 | select_dialect.remove(i); |
286 | } |
287 | var list = langs[select_language.selectedIndex]; |
288 | for (var i = 1; i < list.length; i++) { |
289 | select_dialect.options.add(new Option(list[i][1], list[i][0])); |
290 | } |
291 | select_dialect.style.visibility = list[1].length == 1 ? 'hidden' : 'visible'; |
292 | } |
293 | |
294 | var final_transcript = ''; |
295 | var recognizing = false; |
296 | var ignore_onend; |
297 | var ignore_result; |
298 | var start_timestamp; |
299 | if (!('webkitSpeechRecognition' in window)) { |
300 | upgrade(); |
301 | } else { |
302 | var contentFrame = parent.contentframe; |
303 | var lastText = ""; |
304 | |
305 | start_button.style.display = 'inline-block'; |
306 | var recognition = new webkitSpeechRecognition(); |
307 | recognition.continuous = false; // TRUE |
308 | recognition.interimResults = false; |
309 | |
310 | recognition.onstart = function() { |
311 | recognizing = true; |
312 | showInfo('info_speak_now'); |
313 | start_img.src = 'http://tinybrain.de:8080/speech/mic-animate.gif'; |
314 | }; |
315 | |
316 | recognition.onerror = function(event) { |
317 | if (event.error == 'no-speech') { |
318 | start_img.src = 'http://tinybrain.de:8080/speech/mic.gif'; |
319 | showInfo('info_no_speech'); |
320 | ignore_onend = true; |
321 | } |
322 | if (event.error == 'audio-capture') { |
323 | start_img.src = 'http://tinybrain.de:8080/speech/mic.gif'; |
324 | showInfo('info_no_microphone'); |
325 | ignore_onend = true; |
326 | } |
327 | if (event.error == 'not-allowed') { |
328 | if (event.timeStamp - start_timestamp < 100) { |
329 | showInfo('info_blocked'); |
330 | } else { |
331 | showInfo('info_denied'); |
332 | } |
333 | ignore_onend = true; |
334 | } |
335 | }; |
336 | |
337 | recognition.onend = function() { |
338 | recognizing = false; |
339 | if (ignore_onend) { |
340 | return; |
341 | } |
342 | start_img.src = 'http://tinybrain.de:8080/speech/mic.gif'; |
343 | |
344 | //final_transcript = ""; // DEH HACK |
345 | |
346 | if (!final_transcript) { |
347 | showInfo('info_start'); |
348 | return; |
349 | } |
350 | showInfo(''); |
351 | if (window.getSelection) { |
352 | window.getSelection().removeAllRanges(); |
353 | var range = document.createRange(); |
354 | range.selectNode(document.getElementById('final_span')); |
355 | window.getSelection().addRange(range); |
356 | } |
357 | }; |
358 | |
359 | recognition.onresult = function(event) { |
360 | var interim_transcript = ''; |
361 | if (ignore_result) { |
362 | ignore_result = false; |
363 | return; |
364 | } |
365 | for (var i = event.resultIndex; i < event.results.length; ++i) { |
366 | if (event.results[i].isFinal) { |
367 | var newData = event.results[i][0].transcript; |
368 | //final_transcript += newData; |
369 | final_transcript = newData; |
370 | var frameURL = "LINK/has-speech?q=" + encodeURIComponent(newData) + "&language=" + select_language.selectedIndex + "&sublanguage=" + select_dialect.selectedIndex; |
371 | if (contentFrame && lastText != newData) { |
372 | lastText = newData; |
373 | contentFrame.location.href = frameURL; |
374 | } |
375 | } else { |
376 | interim_transcript += event.results[i][0].transcript; |
377 | } |
378 | } |
379 | final_transcript = capitalize(final_transcript); |
380 | final_span.innerHTML = linebreak(final_transcript); |
381 | interim_span.innerHTML = linebreak(interim_transcript); |
382 | if (/*final_transcript ||*/ interim_transcript) { |
383 | showButtons('inline-block'); |
384 | } |
385 | }; |
386 | |
387 | startRecognition(); |
388 | } |
389 | |
390 | function upgrade() { |
391 | start_button.style.visibility = 'hidden'; |
392 | showInfo('info_upgrade'); |
393 | } |
394 | |
395 | var two_line = /\n\n/g; |
396 | var one_line = /\n/g; |
397 | function linebreak(s) { |
398 | return s.replace(two_line, '<p></p>').replace(one_line, '<br>'); |
399 | } |
400 | |
401 | var first_char = /\S/; |
402 | function capitalize(s) { |
403 | return s.replace(first_char, function(m) { return m.toUpperCase(); }); |
404 | } |
405 | |
406 | function copyButton() { |
407 | if (recognizing) { |
408 | recognizing = false; |
409 | recognition.stop(); |
410 | } |
411 | copy_button.style.display = 'none'; |
412 | copy_info.style.display = 'inline-block'; |
413 | showInfo(''); |
414 | } |
415 | |
416 | function startButton(event) { |
417 | startRecognition(); |
418 | } |
419 | |
420 | function startRecognition() { |
421 | if (recognizing) { |
422 | recognition.stop(); |
423 | ignore_result = true; |
424 | return; |
425 | } |
426 | final_transcript = ''; |
427 | recognition.lang = select_dialect.value; |
428 | recognition.start(); |
429 | ignore_onend = false; |
430 | final_span.innerHTML = ''; |
431 | interim_span.innerHTML = ''; |
432 | start_img.src = 'http://tinybrain.de:8080/speech/mic-slash.gif'; |
433 | showInfo('info_allow'); |
434 | showButtons('none'); |
435 | start_timestamp = event.timeStamp; |
436 | } |
437 | |
438 | function showInfo(s) { |
439 | if (s) { |
440 | for (var child = info.firstChild; child; child = child.nextSibling) { |
441 | if (child.style) { |
442 | child.style.display = child.id == s ? 'inline' : 'none'; |
443 | } |
444 | } |
445 | info.style.visibility = 'visible'; |
446 | } else { |
447 | info.style.visibility = 'hidden'; |
448 | } |
449 | } |
450 | |
451 | var current_style; |
452 | function showButtons(style) { |
453 | if (style == current_style) { |
454 | return; |
455 | } |
456 | current_style = style; |
457 | copy_button.style.display = style; |
458 | copy_info.style.display = 'none'; |
459 | } |
460 | </script> |
461 | ]=]; |
462 | ret render(html); |
463 | } |
464 | |
465 | // frame set |
466 | |
467 | ret render([[ |
468 | <title>TITLE</title> |
469 | |
470 | <frameset rows="280,*"> |
471 | <frame src="LINK/upper"></frame> |
472 | <frame name="contentframe" src="LINK/empty"></frame> |
473 | </frameset> |
474 | ]]); |
475 | } |
476 | |
477 | static S render(S html) { |
478 | ret html.replace("LINK/", rawLink("")).replace("TITLE", getProgramName()); |
479 | } |
480 | |
481 | static L<Entry> makeHistory(L<Map> log) { |
482 | new L<Entry> history; |
483 | for (Map map : log) { |
484 | S in = cast map.get("heard"); |
485 | S out = cast map.get("saying"); |
486 | if (nempty(in) && nempty(out)) { |
487 | new Entry e; |
488 | e.userSaid = in; |
489 | e.botSaid = out; |
490 | e.time = toLong(map.get("done")); |
491 | e.cookie = (S) map.get("cookie"); |
492 | e.logID = toLong(map.get("_id")); |
493 | history.add(e); |
494 | } |
495 | } |
496 | ret history; |
497 | } |
498 | |
499 | static void addToHistory(L<Entry> l) { |
500 | int n = l(history); |
501 | history.addAll(l); |
502 | learnFrom(n); |
503 | } |
504 | |
505 | static void learnFrom(int n) { |
506 | for (Bot bot : bots) pcall { |
507 | bot.learnFrom(history, n); |
508 | } |
509 | } |
510 | |
511 | static void log(Map map) { |
512 | map.put("_id", logLength+1); |
513 | logMap(logName, map); |
514 | ++logLength; |
515 | addToHistory(makeHistory(litlist(map))); |
516 | } |
Began life as a copy of #1002922
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1002944 |
Snippet name: | Pivo Bot English (multi-lingual) |
Eternal ID of this version: | #1002944/1 |
Text MD5: | b2106d3e120b82e818e76a61d0bfa021 |
Transpilation MD5: | e637af660ca0a1daab571c3c67cfb468 |
Author: | stefan |
Category: | javax |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-04-12 17:49:44 |
Source code size: | 14202 bytes / 516 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 855 / 866 |
Referenced in: | [show references] |