diff options
-rw-r--r-- | examples/jarvis.js | 72 | ||||
-rw-r--r-- | tools/claim.js | 4 | ||||
-rw-r--r-- | tools/search.js | 23 | ||||
-rw-r--r-- | utils/ident.js | 20 | ||||
-rw-r--r-- | utils/writewrap.js | 13 |
5 files changed, 77 insertions, 55 deletions
diff --git a/examples/jarvis.js b/examples/jarvis.js index ca58f8b..7b5c64e 100644 --- a/examples/jarvis.js +++ b/examples/jarvis.js @@ -1,5 +1,9 @@ // A bot which responds to `jarvis` with a box +// BUG: The Scheduler, Search, Claims, ident, AND Write Listener can ALL be +// used as extensions for Socket. This would make the code so much easier to +// understand + const Space = require('../space'); const Socket = require('../socket'); const ms = require('../utils/measurespace'); @@ -14,38 +18,44 @@ const wwrap = require('../utils/writewrap'); const Claims = require('../tools/claim'); //// The queue of all writes to be sent to the server @ 200chars/1000ms -var writes = new sched.Queue(1000, 200, (elems) => main.write(elems)); -var main = new Socket(); -var claims = new Claims(detectPrompt); +class MetaSocket extends Socket{ + constructor(world='', delayms=1000){ + super(world); + let self = this; + sched.Queue.call(self, 1000, 200, (elems) => self.write(elems)); + Claims.call(self); + id.call(self); + wwrap.call(self); + self.sender; + self.on('init',(send)=>{ + self.sender = send; + }); + Search.call(this); + } +} +var main = new MetaSocket(); // See ident.js for further documentation, but this basically sets up init functions -id(main, initOnce, init, deinit); -writeListen = new wwrap(main); - -var sender; -function init(send){ - sender = send; // tileUpdates require knowledge of the sender - setTimeout(()=>{writes.enable()},1000); // Would fail if a write were added because it would be within a second of cursor send - writes.enqueue(genNotif().towrite()); -} -function deinit(){ - writes.disable(); -} +main.on('init', (send)=>{ + setTimeout(()=>{main.enable()},1000); + main.enqueue(genNotif().towrite()); +}); +main.on('close', ()=>main.disable()); -function initOnce(){ +main.on('initOnce', ()=>{ timect(); main.on('tileUpdate', tileHandler); // Should only be active after the "control space" of the notification has been established -} +}); //// Management utilities // When a tile changes, processes data into usable form and runs every function in `funcs` w/ that data. // Note that functions can edit inputs function tileHandler(send, source, tiles){ - if (send == sender) return; + if (send == main.sender) return; let tiledata = maketiles(tiles); - claims.handle(send, tiledata.tilespaces, tiledata.locs); + main.handle(send, tiledata.tilespaces, tiledata.locs); } //// "userspace" functions for responses, like to tileUpdates @@ -77,14 +87,14 @@ function notifRefresh(){ let diff = newnotif.copy(); if (typeof notif !== 'undefined') diff.comb(notif, comb.sub); notif = newnotif; - if (notifClaim) claims.unclaim(notifClaim); - notifClaim = claims.claim(newnotif, protectArea); + if (notifClaim) main.unclaim(notifClaim); + notifClaim = main.claim(newnotif, protectArea); return (diff.towrite()); } function timect(){ minsUp++; - writes.enqueue(notifRefresh()); + main.enqueue(notifRefresh()); setTimeout(timect, 60*1000); } @@ -98,27 +108,25 @@ function protectArea(send, tiles, locs, id, space, ctrl){ diff.comb(tile, comb.sub); writelist.push(...diff.towrite()) } - writes.enqueue(writelist); + main.enqueue(writelist); } var search = new Space(); search.adhoc('jarvis'); // The search space is the word jarvis, so whenever that's caught, a relevant function can be called. -var read = new Search(search); +var read = new Search(); +read.match(search, respond); var expire = {}; -function detectPrompt(send, tiles, locs){ // tries to detect the prompt ('jarvis') and calls respond if found. - for (let i=0; i<locs.length; i++){ - let loc = locs[i]; +main.on('fallback', (send, tiles, locs) => { // tries to detect the prompt ('jarvis') and calls respond if found. + for (let loc of locs){ if (read.has(loc)){ clearTimeout(expire[loc]); - delete expire[loc]; read.del(loc); } - let results = read.add(loc, tiles[loc]); - if (results.length > 0) respond(results, send); + read.add(loc, tiles[loc]); expire[loc] = setTimeout(() => {read.del(loc); delete expire[loc];}, 30000); } -} +}); let response = new Space(); response.adhoc('yes, my liege'); @@ -129,7 +137,7 @@ function respond(coord, send){ console.log('called at', coord); callct += 1; response.loc = coord; - writes.enqueue(response.towrite().concat(notifRefresh())); + main.enqueue(response.towrite().concat(notifRefresh())); read.update(response); setTimeout(() => {limits.splice(limits.indexOf(send))}, 5*1000); limits.push(send); diff --git a/tools/claim.js b/tools/claim.js index 721c5ad..b43417b 100644 --- a/tools/claim.js +++ b/tools/claim.js @@ -5,7 +5,7 @@ const ri = require('../utils/rectintersect'); const vec = require('../utils/vec'); const comb = require('../utils/comb'); -module.exports = function(catchall){ +module.exports = function(){ // catchall is called if tileUpdate occurs w/ no relevant claim on a part. let claims = {}; let claimId = 0; @@ -44,6 +44,6 @@ module.exports = function(catchall){ } claim.call(send, diffspace, rellocs, id, claim.space, claim.area); // claim.space should not be modified by the function. it is only present to make functions easier to write } - catchall(send, tilespaces, locs); + this.emit('fallback', send, tilespaces, locs); } } diff --git a/tools/search.js b/tools/search.js index 7f681f0..78e0ee7 100644 --- a/tools/search.js +++ b/tools/search.js @@ -12,11 +12,13 @@ function getComp(index){ return (element,needle) => (element[index] - needle[index] || element[1-index] - needle[1-index]) } -function Search(searchBlock){ // searchBlock should be a Space object. +function Search(){ // searchBlock should be a Space object. this.tiles = {}; // Object which stores Spaces. this.sort = [[],[]]; // Vertically/horizontally sorted list of tiles for fast addition, deletion, and searching + this.spaces = []; + this.calls = []; - this.add = function(loc, space){ // loc should be [tileY,tileX] and space Space. + this.add = function(loc, space, send){ // loc should be [tileY,tileX] and space Space. this.tiles[loc] = space; let inds = Array(2); // Records horizontal and vertical indices for insertion. Then actually inserts the item. [0,1].forEach( ind => { // ind chooses y-or-x @@ -29,8 +31,10 @@ function Search(searchBlock){ // searchBlock should be a Space object. block.forEach( (tile) => { searchspace.comb( this.tiles[tile], comb.add ); }); - coords = searchspace.search(searchBlock); // According to space docs, [] on failure and a character location on success - return vec.add(coords, searchspace.loc); + for (let i=0; i<this.spaces.length; i++){ + let coords = searchspace.search(this.spaces[i]); + if (coords.length) this.calls[i](vec.add(coords, searchspace.loc), send, searchspace); + } } this.block = function(loc,inds,exclude){ @@ -79,6 +83,17 @@ function Search(searchBlock){ // searchBlock should be a Space object. else this.add(tile, tiles[tile]); } } + + this.match = function(space, call){ + this.spaces.push(space); + this.calls.push(call); + } + + this.unmatch = function(space){ + let ind = this.spaces.indexOf(space); + this.spaces.splice(ind, 1); + this.calls.splice(ind, 1); + } } module.exports = Search; diff --git a/utils/ident.js b/utils/ident.js index 187132f..b4fa8ff 100644 --- a/utils/ident.js +++ b/utils/ident.js @@ -2,32 +2,32 @@ const vec = require('../utils/vec'); -module.exports = function identify(sock, initOnce, init, deinit){ - // `sock` should be Socket instance. +module.exports = function identify(){ + // `this` should be Socket instance. // initOnce and init should be functions that act like they describe; initOnce runs once per program execution and init whenever the socket turns back on - sock.on('open', ()=>{ + let self = this; + + self.on('open', ()=>{ // "Pings" the server with a cursor location which is detected and saved by identity() let coords = [Math.floor(Math.random()*100000+16), Math.floor(Math.random()*1000000+16)]; - sock.cursor(coords); - sock.on('cursor', detect); + self.cursor(coords); + self.on('cursor', detect); function detect(pos, send){ if (vec.equals(pos[0],coords)){ - sock.off('cursor', detect); + self.off('cursor', detect); identity(send); } } }); - sock.on('close', deinit); - // Calls initOnce and init on successful identification. let initialized = false; function identity(send){ if (! initialized){ initialized = true; - initOnce(); + self.emit('initOnce'); } - init(send); + self.emit('init', send); } } diff --git a/utils/writewrap.js b/utils/writewrap.js index 3ca7ede..2e2ae07 100644 --- a/utils/writewrap.js +++ b/utils/writewrap.js @@ -1,12 +1,11 @@ // An EventEmitter wrapper for socket.js writes const EventEmitter = require('events'); -class wwrap extends EventEmitter{ - constructor(socket){ - super(); - socket.on('write', (acc) => { // Assumed that none are rejected because I've never seen it - for (let w of acc) this.emit(w); - }); - } +function wwrap(){ // should be called with wwrap.call(socket) + let self = this; + self.on('write', (acc) => { + for (let w of acc) this.emit(w); + }); } + module.exports = wwrap; |