Created
September 1, 2014 00:41
-
-
Save TrevorBasinger/889df1575cbb1dff3bc1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var Future = require('data.future'); | |
var Either = require('data.either'); | |
var State = require('fantasy-states'); | |
var Tuple2 = require('fantasy-tuples').Tuple2; | |
var Tuple3 = require('fantasy-tuples').Tuple3; | |
var IO = require('fantasy-io'); | |
var Maybe = require('pointfree-fantasy/instances/maybe'); | |
var _ = require('ramda'); | |
var http = require('http'); | |
var rl = require('readline'); | |
var daggy = require('daggy'); | |
var OLens = require('fantasy-lenses').Lens.objectLens; | |
var io = require('socket.io-client'); | |
require('pointfree-fantasy').expose(global); | |
///////////////////////////////////////////////////////////////// | |
//// Application | |
//// This application runs in a loop. As notifications are posted | |
//// to the Autobeacon db, this bot will manage dispatching | |
//// notifications. | |
///////////////////////////////////////////////////////////////// | |
///////////////////////////////////////////////////////////////// | |
//// Pure Code | |
///////////////////////////////////////////////////////////////// | |
/* Lens Helpers */ | |
var get = function (lens) { return lens.get(); }; | |
var set = curry (function (obj, lens) { return lens.set (obj); }); | |
///////////////////////////////////////////////////////////////// | |
// Bot Pointed Functor | |
///////////////////////////////////////////////////////////////// | |
Bot = daggy.tagged ('config'); | |
Bot.of = function (c) { return Bot (c); }; | |
Bot.prototype.map = function (f) { return f (this.config); }; | |
///////////////////////////////////////////////////////////////// | |
// Bot Lenses | |
// idLens :: BotConfig -> Lens | |
var idLens = OLens ('id').run; | |
// roleLens :: BotConfig -> Lens | |
var roleLens = OLens ('role').run; | |
///////////////////////////////////////////////////////////////// | |
// Bot Lens Accessors | |
// setId :: id -> Bot -> Bot | |
var setId = curry (function (id) { return compose (Bot.of, set (id), map (idLens)); }); | |
// getId :: Bot -> Int | |
var getId = compose (get, map(idLens)); | |
// setRole :: role -> Bot -> Bot | |
var setRole = function (role) { return compose (Bot.of, set (role), map (roleLens)); }; | |
// getRole :: Bot -> Int | |
var getRole = compose (get, map (roleLens)); | |
// determineRole :: String -> String -> String | |
var determineRole = function (suggested, conflict) { | |
if (suggested === '') { return determineRole ('manager', conflict) } | |
if (suggested === 'manager') { if (conflict === 'manager') { | |
return determineRole ('queue', null); } } | |
if (suggested === 'queue') { if (conflict === 'queue') { | |
return determineRole ('client', null); } } | |
if (suggested === 'client') { return 'client'; } | |
return suggested; | |
} | |
// resolveConflicts :: Config -> Bot -> Bot | |
var resolveConflicts = curry (function (config, bot) { | |
if(config.id === getId (bot)) return bot; | |
var n = determineRole (getRole (bot), config.role); | |
return setRole (n) (bot); | |
}); | |
// main :: ConfigObj -> Socket.IO.Socket -> IO () | |
var main = function (config, s) { | |
var bot = Bot.of (config); | |
return IO.of (s) | |
.chain (function (socket) { | |
socket.on ('status', function (d) { bot = resolveConflicts (d, bot); }); | |
socket.on ('all', function (d) { | |
if (d.fromId !== getId (bot)) { | |
if (d.action === 'statusCheck') { socket.emit ('status', map (I, bot)); }}}); | |
socket.emit ('all', { action: 'statusCheck', fromId: getId (bot) }); | |
return IO.of () | |
}); | |
} | |
///////////////////////////////////////////////////////////////// | |
//// Impure Code | |
///////////////////////////////////////////////////////////////// | |
function randomInt (min, max) { | |
return Math.floor (Math.random() * (max - min + 1)) + min; | |
} | |
var config = { | |
id: randomInt(0, 999999), | |
role: 'manager', | |
status: '' | |
}; | |
main (config, io.connect ('http://localhost:1234')).unsafePerform(); |
I've also looked at Baconjs. I'm not sure how I would apply it in a way that would give me more value that what just socket.io has. I'm interested to hear how you might apply it.
Sorry of the delay on this. I think the Reader
or State
monad can be used in place of Bot
. Then we can use local
or modify
to update and maintain internal state.
Bacon will help us model sockets in a pure way. For instance, we can get tangible streams of status
and all
events which can be mapped over. This eliminates the need for IO
.
What does the server look like? (localhost:1234). I wanted to try to play with it, but i'm struggling to dig deep without seeing it work.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think I may be "doing it wrong" in the main function. I'm not sure how to allow my socket handler make changes to
bot
and have that state kept after the handler exits.