لذا فقد انتهى إنتركوم 18 الخاص بنا ، مع التفضيلات وحالات العمل. كالعادة ، تم دفع مدخل المؤتمر: أولئك الذين أرادوا شراء تذاكر TimePad بالسعر الكامل ، أو ... الحصول على خصم من مستشار الزواحف
مباشرة على الموقع . في العام الماضي ، عملت كرد اتصال مألوف: تترك الهاتف في شكل خاص ، ويتصل بك بافل في دقيقة ويسأل أسئلة ؛ كلما زادت الإجابات الصحيحة ، زاد الخصم. هذه المرة قررنا تغيير الميكانيكا ، مما يجعل الأمر أكثر صعوبة من الناحية الفنية ومن حيث القضايا. تحت القطع - أحشاء Pavlik 2.0 ، مع العقدة الحالية ومآخذ الويب ، لا تنس ارتداء ملابس العمل قبل الفتح.
ميكانيكا المسابقة
تذهب إلى
intercomconf.com من متصفح سطح المكتب ، في الزاوية اليمنى السفلية "يستيقظ" Pavlik في شكل محادثة ويقدم عروض للعب اللعبة. أدخل الرقم ، انقر فوق "هنا هو رقمي" - بعد ذلك ، يرفع Pavel جلسة بين المستعرض والواجهة الخلفية.

إذا ارتفع كل شيء بنجاح ولم يشارك رقمك في السحب بعد ، فسيعرض بول الاتصال على الرقم 8-800. هنا تدخل سحابة Voximplant ويبدأ الاختبار:
الجواب: الموعد النهائي / الموعد النهائي. استناداً إلى ميمي هذا جيد .نعم ، كانت الألغاز شيء من هذا القبيل. تم إجراء ثلاث محاولات لكل سؤال: في البداية كانت هناك صورة "معقدة" ، ثم كانت أبسط وفي النهاية أبسط. أعطت المحاولات الأولى أكبر عدد من النقاط ؛ بعد 5 الألغاز ، أحسب بافيل النقاط وأعطى تذكرة مجانية أو خصم 10 ٪ -30 ٪.
في نفس الوقت ، لدينا reptiloid ذكي بما فيه الكفاية: أصدر رسائل خطأ (إذا قمت بإدخال رقم الهاتف بشكل غير صحيح ، على سبيل المثال) ، قرر أن الرقم قد شارك بالفعل في الرسم ("أرى رقمًا مألوفًا على شاشة هاتفي المحمول غير موجود. محاولة واحدة في يد واحدة - هذه هي القواعد. ") والأهم من ذلك ، ربط المستعرض والسحابة. كيف عمل هذا الجرأة في الرد الآلي؟
في الفكين جنون الزواحف
الجواب: مركز الاتصال. قال ناف.لتجفيفها ، فإن Paul 2.0 عبارة عن جهاز IVR يعمل في سحابتنا. لذلك ، يجب توضيح كل منطق الزواحف في نص JS النصي ، أليس كذلك؟ نعم ولكن لا.
تتم مزامنة الإصدار الثاني من Pavel مع متصفح العميل: على الموقع يعرض Pavel عمليات إعادة التشغيل ، وعلى الهاتف يسمع إجاباتك ، اعتمادًا على تغيير الصور وعرض النتيجة. للوهلة الأولى ، يمكن تنفيذ هذا التفاعل باستخدام
HTTP API الخاص بنا:
- أولاً ، سيقوم المتصفح بتشغيل البرنامج النصي باستخدام طريقة StartScenarios . في الرد ، تُرجع الطريقة المعلمات media_session_access_url و media_session_access_secure_url التي تحتوي على عناوين URL لـ HTTP و HTTPS ، على التوالي ؛
- يمكن التواصل مع النص البرمجي الجاري تشغيله باستخدام عناوين URL المستلمة ؛
- سيقوم البرنامج النصي بإخبار المتصفح بالصور التي سيتم استخدامها وتحديث النتيجة باستخدام طريقة httpRequestAsync .
ولكن كيف "يمسك" متصفح مخصص؟ في الواقع ، في
httpRequestAsync تحتاج إلى تمرير عنوان URL فريد. ونعم ، الصور - يجب أيضًا تخزينها في مكان ما.
لذلك ، بالإضافة إلى نص JS النصي ، استخدمنا الواجهة الخلفية على
express.js مقترنة بـ
socket.io : عندما أدخل الزائر الرقم ، أعطى المتصفح هذا الرقم للواجهة الخلفية عبر http ، وبعد ذلك تحولت جلسة http إلى جلسة على مآخذ توصيل الويب. ونتيجة لذلك ، تواصل البرنامج النصي باستمرار مع الواجهة الخلفية عبر http ، واستخدمت الواجهة الخلفية مآخذ الويب بالفعل لرمي الصور والنقاط المحسوبة بسرعة في المتصفح.
على جانب مآخذ الويب ، بدت الخلفية كما يلي: | 'use strict'; |
| const express = require('express'); |
| const request = require('request'); |
| const low = require('lowdb'); |
| const FileSync = require('lowdb/adapters/FileSync'); |
| |
| var app = express(); |
| var http = require('http'); |
| var server = http.createServer(app); |
| var io = require('socket.io')(http).listen(server); |
| var session = require('express-session')({ |
| secret: 'secret', |
| resave: true, |
| saveUninitialized: true |
| }); |
| var sharedsession = require('express-socket.io-session'); |
| |
| var sockets = {}; |
| var PORT = process.env.PORT || 3001; |
| |
| app.use(session); |
| |
| io.use(sharedsession(session)); |
| |
| io.on('connection', function (socket) { |
| if (socket[socket.handshake.session.caller_id] === undefined && |
| socket.handshake.session.caller_id !== undefined) { |
| sockets[socket.handshake.session.caller_id] = socket |
| } |
| }); |
| |
| app.use((req, res, next) => { |
| let allowedOrigins = [ |
| // allowed hosts |
| ]; |
| let origin = req.headers.origin; |
| if (allowedOrigins.indexOf(origin) > -1) { |
| res.setHeader('Access-Control-Allow-Origin', origin); |
| } |
| res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); |
| res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS'); |
| res.header('Access-Control-Allow-Credentials', true); |
| if (req.method === 'OPTIONS') { |
| res.sendStatus(200); |
| } else { |
| next(); |
| } |
| }) |
ولكن مع ذلك ، تم تخزين معظم المنطق في البرنامج النصي. فكر في الزواحف في هذا الجانب ...
اتبع النص
الجواب: التعلم الآلي. مأخوذة من Instagram Arnie نفسه .من الواضح: تحتاج بالتأكيد إلى توصيل وحدة التعرف على
ASR .
require(Modules.ASR);
من المثير للاهتمام:
- كان هناك كائن أسئلة في البرنامج النصي يحتوي على جميع الإجابات وأسماء ملفات jpg .
في كل مرة يتم تشغيل البرنامج النصي ، يتم خلط الأسئلة باستخدام وظيفة مساعد التبديل العشوائي :
اظهر الكود | function shuffle(a) { |
| var j, x, i; |
| for (i = a.length - 1; i > 0; i--) { |
| j = Math.floor(Math.random() * (i + 1)); |
| x = a[i]; |
| a[i] = a[j]; |
| a[j] = x; |
| } |
| return a; |
| } |
- يقوم معالج "المستوى الأعلى" لمكالمة واردة ( CallAlerting ) بفحص الهاتف من حيث التفرد ، ويحتوي أيضًا على معالجات لتوصيل وإنهاء مكالمة. فقط داخل onCallConnected هناك مكالمة إلى الواجهة الخلفية (اقرأ إلى socketio):
اظهر الكود | VoxEngine.addEventListener(AppEvents.CallAlerting, async (e) => { |
| call.addEventListener(CallEvents.Connected, onCallConnected); |
| call.addEventListener(CallEvents.Disconnected, onCallDisconnected); |
| // ... |
| }) |
| |
| function onCallConnected(e) { |
| call.say(" , ! : , , <say-as stress='2'></say-as>." + |
| " , . . ??? !", |
| Language.RU_RUSSIAN_MALE); |
| call.addEventListener(CallEvents.PlaybackFinished, startGame); |
| call.record({ |
| stereo: true |
| }); |
| call.addEventListener(CallEvents.RecordStarted, async (rec) => { |
| let res = await Net.httpRequestAsync(ws + '/urlResult?caller_id=' + encodeURIComponent(caller_id) + '&url=' + |
| encodeURIComponent(rec.url)) |
| }); |
| } |
- تظهر فقط بداية اللعبة ، حيث يتم فقط خلط الأسئلة ، قطعها وإرسالها إلى الواجهة الخلفية مع مؤشرات الصورة:
اظهر الكود | async function startGame() { |
| call.removeEventListener(CallEvents.PlaybackFinished); |
| shuffle(questions); |
| questions = questions.slice(0, 5); |
| let res = await Net.httpRequestAsync(ws + '/voxResult?caller_id=' + encodeURIComponent(caller_id) + '&data=' + |
| encodeURIComponent(JSON.stringify({ |
| action: "start", |
| // qIndex attempts = 0 |
| data: questions[qIndex].pics[attempts], |
| points: points |
| }))); |
| try { |
| res = JSON.parse(res.text); |
| } catch (err) { |
| Logger.write(err); |
| } |
| if (res.result === true) { |
| Logger.write("===--- The Game has started! ---==="); |
| startASR(); // |
| wireCall(); // ASR |
| } |
| } |
- يقوم startASR بإنشاء مثيل ASR ويشير إلى قاموس التعرف المفضل. عندما يتحدث اللاعب عن الجواب ، توقف الوظيفة ASR وتبدأ في معالجة السمع - onRecognitionResult ؛
- يزيل onRecognitionResult الفائض من الإجابة:
let rr = e[0].replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", ""); rr = rr.replace(/ /g, '');
ثم يبدأ في عد المحاولات والنقاط ، ويصدر أيضًا تعليقات على طول الطريق:
اظهر الكود | let found = questions[qIndex].answers.some(r => rr.indexOf(r) >= 0); |
| Logger.write("FOUND: " + found); |
| if (found) { |
| if (attempts == 0) { |
| points += 5; |
| call.say("<say-as stress='3'></say-as>! !", Language.RU_RUSSIAN_MALE); |
| } else if (attempts == 1) { |
| points += 3; |
| call.say("! .", Language.RU_RUSSIAN_MALE); |
| } else if (attempts == 2) { |
| points += 1; |
| call.say(" … . .", Language.RU_RUSSIAN_MALE); |
| } |
تقوم الوظيفة أيضًا بزيادة المتغيرات بالمحاولات ورقم السؤال من أجل التحول إلى السؤال التالي أو إنهاء اللعبة ؛ - تمنح الوظيفة النهائية gameFinished الواجهة الخلفية مقدار النقاط إذا فاز شخص برمز ترويجي - يمكن رؤيته في المتصفح وسماعه على الهاتف ، لأن بافليك يعبر عن الفوز ؛ بعد الانتهاء من إنهاء المكالمة .
تقترب القائمة العامة للنص المكتوب من 300 سطر ، الجزء الأكبر حجمًا هو معالجة نتيجة التعرف ،
onRecognitionResult .
الحديث الأحفوري
الجواب: فايرفوكس. لدينا كل شيء.بافيل هو ديناصور ، لكنه يبقى محدثًا: يتطور عامًا بعد عام ولا يزال يحب المزاح. نأمل أن تكون قد صنفت الإصدار الثاني من زاحفنا الحي من حيث التنفيذ. شارك بآرائك في التعليقات ، وكن بصحة جيدة وتذكر - بول يحبك!