aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/jarvis.js72
-rw-r--r--tools/claim.js4
-rw-r--r--tools/search.js23
-rw-r--r--utils/ident.js20
-rw-r--r--utils/writewrap.js13
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;