The avatar.js file is the main configuration file that runs the bot. This file contains the functions and APIs used by the bot. Many of these elements are not intended to be user-editable, and those will not be covered in this document. Only the elements that users may need to edit or understand will be covered. These user-relevant elements are as follows.
const R3_SERVER_NAME |
|
const SESSION_TIMEOUT |
|
const USE_CORNELIUS |
|
const GS_INIT |
|
const GS_RUN |
|
const GS_WAIT40 |
|
const GS_ZEROCNT |
|
const GS_HALT |
|
SharedMemory('LiquidUIAvatar').write({sjs:'C:\ \GuiXTWS\\SJS\\TRX.sjs'}); |
|
SharedMemory('WS').write({autoexit:true}); |
|
The remainder of the information in the avatar.js file will not be discussed in this document because it is not meant to be modified by users. Most of the data within this file is essential for the bot's functionality, and it acts as the primary control mechanism for the bot's operation.
Avatar.js Contents
The complete avatar.js file is displayed below.
/*****************************************************************/ /* */ /* Synactive Liquid UI Avatar bot */ /* Copyright (c) 2013-2013 Synactive Inc. All Rights Reserved. */ /* */ /* First draft: August 27 2013 */ /* */ /*****************************************************************/ /***************************************************************** * * * If you want to be reconnected, say, for processing another * * user, please put this line somewhere in your WS script * * * * SharedMemory('avatar').write({loop:true}); * * * * This will cause the system to reconnect again and you can automate a login as another user. * * * *****************************************************************/ const R3_SERVER_NAME = "/H/juneau"; // in seconds, wait before we display message if no FS const SESSION_TIMEOUT = 5; // Synactive Inc Cornelius const USE_CORNELIUS = true; //SharedMemory('LiquidUIAvatar').write({sjs:'C:\\GuiXTWS\\SJS\\TRX.sjs'}); SharedMemory('WS').write({autoexit:true}); const GS_INIT = 0; const GS_RUN = 1; // wait for num connections to go down to zero before GS_HALT const GS_WAIT40 = 2; // we are at zero connections const GS_ZEROCNT= 3; const GS_HALT = 4; // final state, bye Object.InstanceID = 0; GWAConnection.prototype.onConnect = function() { } GWAConnection.prototype.onReceiveFromServer = function(nType, nMessage, iSession, iOriginatingSession) { this.lFromServerStatus = nType; println('onReceiveFromServer nType='+nType); println(system.stringify(nMessage)); this.touch(); } // A close connection can come from various places // 1. Web Session times out. As determined by SESSION_TIMEOUT value // 2. A graceful exit, as indicated by DIAG CLOSE CONNECTION bit // 3. Forced network termination // // In all cases, this callback is invoked when a hard TCP IP connection // ends. This will be the last activity on this object; and the // final callback. After this, the JS object is no longer linked to // its C++ counterpart. GWAConnection.prototype.onClose = function() { this.bConnectionTerminated = true; println('Connection '+this._toHandle()+' terminated'); } // update the lasttick of this session GWAConnection.prototype.touch = function() { this.lasttick = GWWebServer.HTTICKS(); } GWAConnection.TPS_SESSION_TIMEOUT = SESSION_TIMEOUT * GWWebServer.TPS; GWAConnection.prototype.getTimeoutDuration = function() { return GWAConnection.TPS_SESSION_TIMEOUT; } //-------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- // GWAMenu object //-------------------------------------------------------------------- // GWAMenu represents a menu option // Top level menu is declared in vivien as // vivien.tm = { "e": [xx, yy]; "Elements": array of GWAMenu } // Pop-up menus contains "e"; that identifies the children of this popup // The top level children are found in "vivien.tm.e" function GWAMenu(argVivien) { this._vivien = argVivien; // dontenum } GWAMenu.prototype.onSetMenu = function(nIdx, nParentIdx, szLabel, iFlag, szInfo, szAccel, evtArray) { } //------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- // GWAVivien object
//------------------------------------------------ // This is the object used to create a message of Vivien arrays function GWAVivien() { // do vivien object initialization here } // called by infrastructure to create a control object GWAVivien.prototype.onConstructControl = function() { return {}; } // context menu & application toolbar GWAVivien.prototype.onConstructCmTb = function() { return {}; } GWAVivien.prototype.onConstructMenu = function(iCnt) { // top level object to hold elements and 'e' this.tm = {}; // top level menu this.tm.Elements = [iCnt]; var i; for(i=0; i<iCnt; i++) this.tm.Elements[i] = new GWAMenu(this); return this.tm.Elements; } // Table column attribute GWAVivien.prototype.onConstructColumnAttribute = function() { return {}; } // Table cell GWAVivien.prototype.onConstructTableCell = function() { return {}; } // TabStrip GWAVivien.prototype.onConstructTabStrip = function() { return {}; } // TableTree GWAVivien.prototype.onConstructTableTree = function() { return {}; } // ImageControl GWAVivien.prototype.onConstructImage = function() { return {}; } // called by infrastructure after completion of total construction // of object GWAVivien.prototype.onConstructionComplete = function() { } // HTML GWAVivien.prototype.onConstructHTML = function() { return {}; } // Object GWAVivien.prototype.onConstructObject = function() { return {}; } // called by infrastructure to construct a vivien object to be // populated. The call here allows each connection to be in control // of how a vivien will look GWAConnection.prototype.onConstructVivien = function() { var obj = new GWAVivien(); // if neccessary, we can do some processing here // this exists in GWAMessage.data // dontenum obj._connection = this; return obj; } //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- // GWA object //--------------------------------------------------------------------- // GWA is defined is defined DGWA.cpp // GWA.prototype.process_check = function() { var iProcessed = 0; switch(this.state) { case GS_INIT: try { SharedMemory('avatar').write({loop:false}); var connection = this._connect(this.r3Conn); this.connections[connection._toHandle()] = connection; this.state = GS_RUN; // set the GWA application object in the connection connection.GWA = this; } catch(err) { this.state = GS_HALT; println(err); } break; case GS_RUN: var TPS_NOW = GWWebServer.HTTICKS(); for(var keyHandle in this.connections) { var pConnection = this.connections[keyHandle]; if(pConnection.bConnectionTerminated) { println('[process_check] Connection terminated'); this.state = GS_WAIT40; delete this.connections[keyHandle]; } if((pConnection.lasttick + pConnection.getTimeoutDuration() ) < TPS_NOW) { if(!pConnection.bTimeoutMessageShowed) { println('[process_check] Connection '+keyHandle+' has no ') println('activity for '+SESSION_TIMEOUT+' seconds, please check script'); pConnection.bTimeoutMessageShowed = true; pConnection._shutdown(); this.state = GS_WAIT40; delete this.connections[keyHandle]; } } } break; case GS_WAIT40: println(this.getRunningCount()+ ' connections'); if(this.getRunningCount() == 0) this.state = GS_ZEROCNT; break; case GS_ZEROCNT: // zero connections, we can start afresh if need to if(SharedMemory('avatar').read().loop) this.state = GS_INIT; else this.state = GS_HALT; break; } iProcessed += this._check(); return iProcessed; } GWA.prototype.getRunningCount = function() { return this._getRunningCount(); } GWA.prototype.isStopEventSignaled = function() { var bStop = this.state==GS_HALT; return bStop; } GWA.prototype.shutdown = function() {} var g_Running = true; //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- // Main loop //--------------------------------------------------------------------- function processFTELoop(application) { // turn on traces //if(TRACE_TRAFFIC) vGWA._traceTraffic(1); //testconnect(vGWA); var iWait = 2; var iNoProc = 0; var iProcessed = 0; for(;g_Running;) { var bStopEventSignaled = application.isStopEventSignaled(); if(bStopEventSignaled || system._ctrlc()) { if(!g_bExitPending) { application.shutdown(); g_bExitPending = true; // set flag to prevent client from reconnecting again print('Exiting ..'); // wait until all the connections are shutdown completely g_Running = false; } else if(application.getRunningCount() == 0) { break; } } if(iWait > 0) Thread.sleep(iWait); iProcessed = application.process_check(); if(iProcessed > 0) { iWait = 0; iNoProc = 0; } else { iNoProc++; if (iNoProc % 50 == 0) system.gc(); if(iNoProc < 3) iWait = 3; // 0 - 2 else if(iNoProc < 4) iWait = 8; // 3 else if(iNoProc < 8) iWait = 12; // 4 - 7 else if(iNoProc < 9) iWait = 50; // 8 else if(iNoProc <13) iWait = 350; // 9 - 12 else if(iNoProc <20) iWait = 450; // 13- 19 else if(iNoProc < 300) iWait = 1000; else { iWait = 1000; system.gc(); iNoProc = 8; // start over // println('Loop reset count'); } } } application = null; return; } function performRun() { var vGWA = new GWA({cornelius:USE_CORNELIUS}); vGWA.state = GS_INIT; vGWA.r3Conn = {}; vGWA.r3Conn.scSvrName = R3_SERVER_NAME; vGWA.connections = {}; processFTELoop(vGWA); delete vGWA.connections; vGWA = void 0; system.gc(); } function main() { performRun(); } main();