Before moving on with my (fab) game, I have a quick look at my fab.js apps dealing with the player store. Hoepfully, I might be able to clean them up or, better yet, get some test coverage for them.
Much of the player store code is wrapped in my
if_body
(fab) app or in the comet_view
resource which establishes the comet session and adds players to the game:( /chat/ )The
( if_body(
function () {
var msg = JSON.parse(this.toString());
msg.body = msg.say.substr(0,100);
broadcast(comet_player_say(JSON.stringify(msg)));
} ) )
( /bounce/ )
( if_body(
function () {
update_player_status(JSON.parse(""+this));
broadcast(comet_bounce_player(this));
} ) )
( /^\/comet_view/ )
( broadcast_new )
( store_player )
( init_comet )
( player_from_querystring )
if_body
(fab) app fires the supplied function if the downstream (i.e. browser) supplied a body, which it would do by POSTing data. What I notice while looking through the store_player
and init_comet
apps is that I do a lot of if-response-body-then-do:function init_comet (app) {It could be especially helpful to factor that out of the player store code. Doing so would allow me to separate the player store entirely from the (fab) apps:
return function () {
var out = this;
return app.call( function listener(obj) {
if (obj && obj.body && obj.body.uniq_id) {
do_comet.call(out, obj);
}
else if (obj && obj.status) {
out(obj)();
}
return listener;
});
};
}
function store_player (app) {I do not think that I need a ternary (fab) app. What I need is a (fab) app that takes a callback to fire if there is a downstream response. Fab.js already includes
return function () {
var out = this;
return app.call( function listener(obj) {
if (obj && obj.body && obj.body.id) {
var new_id = obj.body.id;
if (!players[new_id]) {
puts("[store_player] adding: " + new_id);
// player store code here
}
else if (players[new_id].uniq_id == obj.body.uniq_id) {
puts("[store_player] refreshing session: " + new_id);
// player store code here
}
else {
out();
}
}
out(obj);
return listener;
});
};
}
fab.tap
that does something similar, except that it does not include the downstream response when invoking the callback. The fab.tap
app takes the callback as an argument, then returns a binary app:exports.app = function( fn ) {To get the upstream response, it is not sufficient to
return function( app ) {
return function() {
fn();
return app.call( this );
}
}
}
app.call()
the upstream app with the downstream listener (always set to this
by fab.js). Instead, I have to app.call
with a listener for the upstream response:function if_response(fn) {With that, I can refactor the
return function(app) {
return function() {
var out = this;
return app.call(function listener(obj) {
if (obj && obj.body) {
fn.call(out, obj.body);
}
out(obj);
return listener;
});
};
};
}
store_player
function as a side-effect only function. This allows me to rewrite the comet call stack as:( /^\/comet_view/ )I am not sure how I feel about that syntax, so I will stop there for today. If I decide that I like it after sleeping on it, I will delete this exploratory code and BDD the real thing. Otherwise I will move onto to other matters.
( broadcast_new )
( if_response (store_player) )
( init_comet )
( player_from_querystring )
Day #164
No comments:
Post a Comment