<commit_before>//
// Loader for Strider extension modules.
//

var async = require('async'),
    connect = require('connect'),
    fs = require('fs'),
    path = require('path'),
    Step = require('step');

// p is file ? return json content : false
var checkStatFile = function(p, cb){
  var json;
  try {
    var json = require(path.resolve(p))
  } catch (e) {
    if (e.code == "MODULE_NOT_FOUND")
      return cb(null,false);
    else{
      console.log("!!", e)
      return cb(e)
    }
  }
  return cb(null, json)
}

var checkStrider = function(pth, cb){
  checkStatFile(path.join(pth, "strider.json"), function(err, res){
    if (err) return cb(err);
    if (!res) return cb(null, false);

    if (!res.id){
      console.error("Error in module: ", pth, " : strider.json must include an 'id'")
    }
    var out = [res.id || pth, res]
    cb(err, out)
  })
}

var checkPackageJson = function(pth, cb){
  var p = path.join(pth, "package.json")
  checkStatFile(p, function(err, exists){
    if (err) return cb(err);
    if (!exists || !exists.strider){ return cb(null, false)};
    var res = [exists.name, exists.strider]
    return cb(null, res);
  })
}

var checkModule = function(pth, cb){
  checkStrider(pth, function(err, res){
    if (err) return cb(err);
    if (res){
      res[1].dir = pth;
      return cb(null, res)
    }

    checkPackageJson(pth, function(err, res){
      if (err) return cb(err);
      if (res){
        res[1].dir = pth
        return cb(null, res)
      }

      return cb(null, false)
    })

  })
}

// fs.readdir list of paths in parallel.
// used when `dir` arg is an array.
function readEntries(dirs, cb) {
  var funcs = []
  dirs.forEach(function(dir) {
    funcs.push(function(c) {
      fs.readdir(dir, function(err, entries) {
        var l = [];
        entries.forEach(function(entry) {
          l.push(path.join(dir, entry))
        })
        c(err, l)
      })
    })
  })
  async.parallel(funcs, function(err, results) {
      if (err) {
        return cb(err, null);
      }
      // Flatten results and return
      var flat = [].concat.apply([], results);
      cb(null, flat);
    }
  );
}

var findModuleDirs = function(dir, cb) {
    // find top-level module dirs
    if (Array.isArray(dir)) {
      // dir is a list of paths
      readEntries(dir, cb)
    } else {
      // dir is a single path value
      fs.readdir(dir, function(err, entries) {
        if (err || !entries) {
          return cb(err, null);
        }
        var l = [];
        entries.forEach(function(entry) {
          l.push(path.join(dir, entry))
        });
        return cb(null, l);
      });
    }
}

var checkModules = function(modules, cb){
  async.map(modules || [], checkModule, cb);
}

var parseModules = function(modules, cb){
  var extensions = []
  modules.forEach(function(module){
    if (module){
      var out = module[1]
      out.weight = out.weight || -1
      out.typ= "json"
      out.id = out.id || module[0] || out.name
      extensions.push(out)
    }
  })
  return cb(null, extensions)
}

//
// ### Locate Strider Extensions
//
// Under a specified path **dir** look for directories containing file
// 'strider.json'.  These are considered Strider modules. **dir** may be either a string or a list of strings.
//
// Or look for package.json with a "strider" key inside. (Preferred way now)
//
// **cb** is a function of signature cb(err, extensions) where extensions is an
// {id : config} mapping on success and err is an error on failure.
//
function findExtensions(dir, cb) {

  findModuleDirs(dir, function(err, modules){
    checkModules(modules, function(err, extensions){
      parseModules(extensions, cb);
    })
  })
}

var fail = function(msg){
  console.error("Error loading extension: %s", msg);
  process.exit(1);
}

var findAndSortExtensions = function(dir, cb){
  findExtensions(dir, function(err, loaded){
    if (err) return cb(err);

    // Sort by weight
    loaded = loaded.sort(function (a, b) { return a.weight - b.weight; });
    cb(null, loaded);
  });

}

var initWorker = function(l, context, cb){
  if (typeof(l.worker) === 'string') {
      l.worker = require(path.resolve(path.join(l.dir, l.worker)))
      l.worker = l.worker.worker || l.worker

    if (typeof(l.worker) === 'function') {
      try {
        l.worker(context, cb);
      } catch (e) {
        console.log("Error loading extension:", e, " in directory:", l.dir)
        process.exit(1)
      }
    } else {
      console.log("!! WORKER ISNT A FUNCTION", l)
    }
  } else {
    cb(null, null)
  }
}

var initWorkerExtensions = function(dir, ctx, cb){
  console.log("Looking for worker extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);

    var initWorkerCurried = function(l, cb){
      return initWorker(l, ctx, cb);
    }

    async.map(loaded, initWorkerCurried, function(err, loaded){
      cb(null, loaded || []);
    })
  })
}

var initRunnerExtensions = function(dir, ctx, cb){
  console.log("Looking for worker extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);

    var runners = []
    for (var i = 0; i<loaded.length; i++){
      var l = loaded[i];
      if (l.runner){
        var runner = require(path.resolve(path.join(l.dir, l.runner)))
        runner = runner.runner || runner;
        runners.push(runner)
      }
    }

    cb(null, runners);
  })
}

var contextRoute = function(context, appInstance, l){
  return {
    get:function(p, f) {
      context.extensionRoutes.push(
        {method:"get", path:p, extension:l.dir});
      appInstance.get.apply(appInstance, arguments);
    },
    post:function(p, f) {
      context.extensionRoutes.push(
        {method:"post", path:p, extension:l.dir});
      appInstance.post.apply(appInstance, arguments);
    },
    delete:function(p, f) {
      context.extensionRoutes.push(
        {method:"delete", path:p, extension:l.dir});
      appInstance.delete.apply(appInstance, arguments);
    },
    put:function(p, f) {
      context.extensionRoutes.push(
        {method:"put", path:p, extension:l.dir});
      appInstance.put.apply(appInstance, arguments);
    }
  }
};

var initWebAppExtensions = function(dir, context, appInstance, cb){

  var initWebApp = function(l, cb){
    if (l.webapp && typeof(l.webapp) == "string") {
      l.webapp = require(path.resolve(path.join(l.dir, l.webapp)))
      l.webapp = l.webapp.webapp || l.webapp
    }

    if (l.webapp){
      // Extensions should use context.route.<method>() to add routes
      context.route = contextRoute(context, appInstance, l)

      // Add a static fileserver mounted at /ext/$module/ which maps to
      // moduledir/static
      appInstance.use('/ext/' + path.basename(l.dir),
          connect.static(path.join(l.dir, "static")));
    }

    if (l.templates){
      for (var k in l.templates){
        templates[k] = l.templates[k]

        if (/\.html/.test(l.templates[k])){
          templates[k] = l.dir + '/' + l.templates[k];
        }
      }
    }

    if (typeof(l.webapp) === 'function') {
      try {
        return l.webapp(context, cb);
      } catch (e) {
        console.trace();
        fail("error loading extension: "+ e+ " in directory:" + l.dir)
      }
    } else {
      if (l.webapp){
        console.log("!! WEBAPP ISNT FUNCTION", l)
        cb(1)
      } else {
        return cb(null)
      }
    }
  }

  console.log("looking for webapp extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);
    async.map(loaded, initWebApp, function(err, loaded){
      cb(null, loaded || []);
    })
  })
}

var listWorkerExtensions = function(dir, cb){
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return cb(err);

    loaded = loaded.filter(function(x){ return !!x.worker})
    cb(null, loaded)
  })
}

// Exported functions
module.exports = {

//
// ### Initialize Strider Extensions
//
// Find, load and initialize extenions of type ***type*** under extension
// directory ***extdir*** ***type*** may be one of "webapp" or "worker".
//
// Context should be a Strider context object with keys:
//  - config (strider config object)
//  - emitter (global eventemitter)
//  - extensionRoutes (list of webapp routes)
//  - registerTransportMiddleware (function)
//
// ***appInstance*** should be an ExpressJS app instance, and is only needed
// for webapp extensions. Can be left null/undefined for worker extensions.
//
// ***cb*** is a callback to be executed when all modules are initialized.
//
//
  initWorkerExtensions : initWorkerExtensions,
  initWebAppExtensions: initWebAppExtensions,
  initRunnerExtensions: initRunnerExtensions,
  listWorkerExtensions: listWorkerExtensions,

  // Exposed only for unit tests...
  _findExtensions: findExtensions,
};
<commit_msg>better id's<commit_after>//
// Loader for Strider extension modules.
//

var async = require('async'),
    connect = require('connect'),
    fs = require('fs'),
    path = require('path'),
    Step = require('step');

// p is file ? return json content : false
var checkStatFile = function(p, cb){
  var json;
  try {
    var json = require(path.resolve(p))
  } catch (e) {
    if (e.code == "MODULE_NOT_FOUND")
      return cb(null,false);
    else{
      console.log("!!", e)
      return cb(e)
    }
  }
  return cb(null, json)
}

var checkStrider = function(pth, cb){
  checkStatFile(path.join(pth, "strider.json"), function(err, res){
    if (err) return cb(err);
    if (!res) return cb(null, false);

    if (!res.id){
      console.error("Error in module: ", pth, " : strider.json must include an 'id'")
    }
    var out = [res.id || pth, res]
    cb(err, out)
  })
}

var checkPackageJson = function(pth, cb){
  var p = path.join(pth, "package.json")
  checkStatFile(p, function(err, exists){
    if (err) return cb(err);
    if (!exists || !exists.strider){ return cb(null, false)};
    var res = [exists.name, exists.strider]
    return cb(null, res);
  })
}

var checkModule = function(pth, cb){
  checkStrider(pth, function(err, res){
    if (err) return cb(err);
    if (res){
      res[1].dir = pth;
      return cb(null, res)
    }

    checkPackageJson(pth, function(err, res){
      if (err) return cb(err);
      if (res){
        res[1].dir = pth
        return cb(null, res)
      }

      return cb(null, false)
    })

  })
}

// fs.readdir list of paths in parallel.
// used when `dir` arg is an array.
function readEntries(dirs, cb) {
  var funcs = []
  dirs.forEach(function(dir) {
    funcs.push(function(c) {
      fs.readdir(dir, function(err, entries) {
        var l = [];
        entries.forEach(function(entry) {
          l.push(path.join(dir, entry))
        })
        c(err, l)
      })
    })
  })
  async.parallel(funcs, function(err, results) {
      if (err) {
        return cb(err, null);
      }
      // Flatten results and return
      var flat = [].concat.apply([], results);
      cb(null, flat);
    }
  );
}

var findModuleDirs = function(dir, cb) {
    // find top-level module dirs
    if (Array.isArray(dir)) {
      // dir is a list of paths
      readEntries(dir, cb)
    } else {
      // dir is a single path value
      fs.readdir(dir, function(err, entries) {
        if (err || !entries) {
          return cb(err, null);
        }
        var l = [];
        entries.forEach(function(entry) {
          l.push(path.join(dir, entry))
        });
        return cb(null, l);
      });
    }
}

var checkModules = function(modules, cb){
  async.map(modules || [], checkModule, cb);
}

var parseModules = function(modules, cb){
  var extensions = []
  modules.forEach(function(module){
    if (module){
      var out = module[1]
      out.weight = out.weight || -1
      out.typ= "json"
      out.id = out.id || module[0].match(/([a-z-]*)$/)[0] || out.name || module[0]
      extensions.push(out)
    }
  })
  return cb(null, extensions)
}

//
// ### Locate Strider Extensions
//
// Under a specified path **dir** look for directories containing file
// 'strider.json'.  These are considered Strider modules. **dir** may be either a string or a list of strings.
//
// Or look for package.json with a "strider" key inside. (Preferred way now)
//
// **cb** is a function of signature cb(err, extensions) where extensions is an
// {id : config} mapping on success and err is an error on failure.
//
function findExtensions(dir, cb) {

  findModuleDirs(dir, function(err, modules){
    checkModules(modules, function(err, extensions){
      parseModules(extensions, cb);
    })
  })
}

var fail = function(msg){
  console.error("Error loading extension: %s", msg);
  process.exit(1);
}

var findAndSortExtensions = function(dir, cb){
  findExtensions(dir, function(err, loaded){
    if (err) return cb(err);

    // Sort by weight
    loaded = loaded.sort(function (a, b) { return a.weight - b.weight; });
    cb(null, loaded);
  });

}

var initWorker = function(l, context, cb){
  if (typeof(l.worker) === 'string') {
      l.worker = require(path.resolve(path.join(l.dir, l.worker)))
      l.worker = l.worker.worker || l.worker

    if (typeof(l.worker) === 'function') {
      try {
        l.worker(context, cb);
      } catch (e) {
        console.log("Error loading extension:", e, " in directory:", l.dir)
        process.exit(1)
      }
    } else {
      console.log("!! WORKER ISNT A FUNCTION", l)
    }
  } else {
    cb(null, null)
  }
}

var initWorkerExtensions = function(dir, ctx, cb){
  console.log("Looking for worker extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);

    var initWorkerCurried = function(l, cb){
      return initWorker(l, ctx, cb);
    }

    async.map(loaded, initWorkerCurried, function(err, loaded){
      cb(null, loaded || []);
    })
  })
}

var initRunnerExtensions = function(dir, ctx, cb){
  console.log("Looking for worker extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);

    var runners = []
      console.log(">>>",dir,  loaded)
    for (var i = 0; i<loaded.length; i++){
      var l = loaded[i];
      if (l.runner){
        var runner = require(path.resolve(path.join(l.dir, l.runner)))
        runner = runner.runner || runner;
        runners.push(runner)
      }
    }

    cb(null, runners);
  })
}

var contextRoute = function(context, appInstance, l){
  return {
    get:function(p, f) {
      context.extensionRoutes.push(
        {method:"get", path:p, extension:l.dir});
      appInstance.get.apply(appInstance, arguments);
    },
    post:function(p, f) {
      context.extensionRoutes.push(
        {method:"post", path:p, extension:l.dir});
      appInstance.post.apply(appInstance, arguments);
    },
    delete:function(p, f) {
      context.extensionRoutes.push(
        {method:"delete", path:p, extension:l.dir});
      appInstance.delete.apply(appInstance, arguments);
    },
    put:function(p, f) {
      context.extensionRoutes.push(
        {method:"put", path:p, extension:l.dir});
      appInstance.put.apply(appInstance, arguments);
    }
  }
};

var initWebAppExtensions = function(dir, context, appInstance, cb){

  var initWebApp = function(l, cb){
    if (l.webapp && typeof(l.webapp) == "string") {
      l.webapp = require(path.resolve(path.join(l.dir, l.webapp)))
      l.webapp = l.webapp.webapp || l.webapp
    }

    if (l.webapp){
      // Extensions should use context.route.<method>() to add routes
      context.route = contextRoute(context, appInstance, l)

      // Add a static fileserver mounted at /ext/$module/ which maps to
      // moduledir/static
      appInstance.use('/ext/' + path.basename(l.dir),
          connect.static(path.join(l.dir, "static")));
    }

    if (l.templates){
      for (var k in l.templates){
        templates[k] = l.templates[k]

        if (/\.html/.test(l.templates[k])){
          templates[k] = l.dir + '/' + l.templates[k];
        }
      }
    }

    if (typeof(l.webapp) === 'function') {
      try {
        return l.webapp(context, cb);
      } catch (e) {
        console.trace();
        fail("error loading extension: "+ e+ " in directory:" + l.dir)
      }
    } else {
      if (l.webapp){
        console.log("!! WEBAPP ISNT FUNCTION", l)
        cb(1)
      } else {
        return cb(null)
      }
    }
  }

  console.log("looking for webapp extensions under %s", dir);
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return fail(err);
    async.map(loaded, initWebApp, function(err, loaded){
      cb(null, loaded || []);
    })
  })
}

var listWorkerExtensions = function(dir, cb){
  findAndSortExtensions(dir, function(err, loaded){
    if (err) return cb(err);

    loaded = loaded.filter(function(x){ return !!x.worker})
    cb(null, loaded)
  })
}

// Exported functions
module.exports = {

//
// ### Initialize Strider Extensions
//
// Find, load and initialize extenions of type ***type*** under extension
// directory ***extdir*** ***type*** may be one of "webapp" or "worker".
//
// Context should be a Strider context object with keys:
//  - config (strider config object)
//  - emitter (global eventemitter)
//  - extensionRoutes (list of webapp routes)
//  - registerTransportMiddleware (function)
//
// ***appInstance*** should be an ExpressJS app instance, and is only needed
// for webapp extensions. Can be left null/undefined for worker extensions.
//
// ***cb*** is a callback to be executed when all modules are initialized.
//
//
  initWorkerExtensions : initWorkerExtensions,
  initWebAppExtensions: initWebAppExtensions,
  initRunnerExtensions: initRunnerExtensions,
  listWorkerExtensions: listWorkerExtensions,

  // Exposed only for unit tests...
  _findExtensions: findExtensions,
};
<|endoftext|>


<commit_before>// VoteServ - standalone irc vote bot written in node.js
var log = require('log-simple')({init: false});

var VERSION = '0.2.0';

log.info('VoteServ v' + VERSION + ' starting...');
log.info('Written with lots of <3 for brenden');

// parse config
var config = require('./config.json');
if (config && config.network
  && config.network.address && config.network.port && config.network.channels
  && config.network.nick) {
    log.info('Loaded config from config.json -', JSON.stringify(config));
} else {
  log.error('Invalid config, see README.md');
  process.exit(1);
}

// irc library
var coffea = require('coffea'),
    net    = require('net');

// connect to server
var stream = net.connect({
  port: config.network.port,
  host: config.network.address
});
var client = coffea(stream);

// set nick and user information
client.nick(config.network.nick);
client.user(config.network.nick, config.network.nick);

// bot is connected to network, (identify and) join channels
client.on('motd', function (motd) {
  if (config.network.nickserv) {
    client.send('NickServ', 'IDENTIFY ' + config.network.nickserv);
  }

  client.join(config.network.channels);
});

// bot begins here

var votes = {};

// parse "!voteACTION USER" and "!vote ACTION USER" commands
// e.g. !voteban brenden
function parseVote(event, cmd, args) {
  if (!cmd) cmd = args.shift();
  if (args.length > 0) {
    var votefor = cmd + '_' + args[0];
    var user = event.user.getNick(); // TODO: get NickServ account
    votes[votefor] = votes[votefor] || [];

    if (votes[votefor].indexOf(user) > -1) {
      client.send(event.channel ? event.channel : event.user,
        'You already voted to \x02' + cmd + '\x02 \x02' + args[0] +
        '\x02. (Votes: \x02' + votes[votefor].length + '\x02)');
      return;
    }

    log.debug(user, 'voted to', cmd, args[0]);
    votes[votefor].push(user);

    client.send(event.channel ? event.channel : event.user,
      user + ' voted to \x02' + cmd + '\x02 \x02' + args[0] +
      '\x02. (Votes: \x02' + votes[votefor].length + '\x02)');
  } else {
    client.send(event.channel ? event.channel : event.user,
      'Not enough arguments.');
  }

  // TODO: special votes, like voteban/votekline
  switch (cmd) {
    //case 'kline':
    //  if (args.length >= 1) {
    //    log.debug(event.user.getNick(), 'voted to kline', args[0]);
    //  } else {
    //    client.send(event.channel ? event.channel : event.user,
    //        'Not enough arguments.');
    //  }
    //break;
  }

  return;
}

function parseCommand(event, cmd, args) {
  if (cmd.substr(0, 4) == "vote") return parseVote(event, cmd.substr(4), args);
  else {
    switch (cmd) {
      case 'who':
      case 'whovoted':
        if (args.length > 1) {
          // !who (voted) (to) ACTION USER
          if ((args.length > 2) && (args[0] == 'voted')) args.shift();
          // !whovoted (to) ACTION USER
          if ((args.length > 2) && (args[0] == 'to')) args.shift();

          // store vote with key ACTION_USER
          var votefor = args[0] + '_' + args[1];
          if (votes[votefor]) {
            var whovoted = votes[votefor].join(', ');
            client.send(event.user,
              'The following people voted to \x02' + args[0] + '\x02 \x02' +
              args[1] + '\x02: ' + whovoted +
              '. (Votes: \x02' + votes[votefor].length + '\x02)');
          } else client.send(event.channel ? event.channel : event.user,
            'No votes to \x02' + args[0] + '\x02 \x02' + args[1] + '\x02.');
        } else {
          client.send(event.channel ? event.channel : event.user,
            'Not enough arguments.');
        }
      break;
    }
    return;
  }
}

// parse channel messages
client.on('message', function(event) {
  if (event.message.substr(0, 1) == '!') { // prefix parsing
    var args = event.message.substr(1).split(' ');
    var cmd = args.shift();
    return parseCommand(event, cmd, args.length > 0 ? args : []);
  }
});

// parse private messages
client.on('privatemessage', function(event) {
  var args = event.message.split(' ');
  var cmd = args.shift();
  return parseCommand(event, cmd, args.length > 0 ? args : []);
});
<commit_msg>add source, version and issue commands<commit_after>// VoteServ - standalone irc vote bot written in node.js
var log = require('log-simple')({init: false});

var VERSION = '0.2.0';

log.info('VoteServ v' + VERSION + ' starting...');
log.info('Written with lots of <3 for brenden');

// parse config
var config = require('./config.json');
if (config && config.network
  && config.network.address && config.network.port && config.network.channels
  && config.network.nick) {
    log.info('Loaded config from config.json -', JSON.stringify(config));
} else {
  log.error('Invalid config, see README.md');
  process.exit(1);
}

// irc library
var coffea = require('coffea'),
    net    = require('net');

// connect to server
var stream = net.connect({
  port: config.network.port,
  host: config.network.address
});
var client = coffea(stream);

// set nick and user information
client.nick(config.network.nick);
client.user(config.network.nick, config.network.nick);

// bot is connected to network, (identify and) join channels
client.on('motd', function (motd) {
  if (config.network.nickserv) {
    client.send('NickServ', 'IDENTIFY ' + config.network.nickserv);
  }

  client.join(config.network.channels);
});

// bot begins here

var votes = {};

// parse "!voteACTION USER" and "!vote ACTION USER" commands
// e.g. !voteban brenden
function parseVote(event, cmd, args) {
  if (!cmd) cmd = args.shift();
  if (args.length > 0) {
    var votefor = cmd + '_' + args[0];
    var user = event.user.getNick(); // TODO: get NickServ account
    votes[votefor] = votes[votefor] || [];

    if (votes[votefor].indexOf(user) > -1) {
      client.send(event.channel ? event.channel : event.user,
        'You already voted to \x02' + cmd + '\x02 \x02' + args[0] +
        '\x02. (Votes: \x02' + votes[votefor].length + '\x02)');
      return;
    }

    log.debug(user, 'voted to', cmd, args[0]);
    votes[votefor].push(user);

    client.send(event.channel ? event.channel : event.user,
      user + ' voted to \x02' + cmd + '\x02 \x02' + args[0] +
      '\x02. (Votes: \x02' + votes[votefor].length + '\x02)');
  } else {
    client.send(event.channel ? event.channel : event.user,
      'Not enough arguments.');
  }

  // TODO: special votes, like voteban/votekline
  switch (cmd) {
    //case 'kline':
    //  if (args.length >= 1) {
    //    log.debug(event.user.getNick(), 'voted to kline', args[0]);
    //  } else {
    //    client.send(event.channel ? event.channel : event.user,
    //        'Not enough arguments.');
    //  }
    //break;
  }

  return;
}

function parseCommand(event, cmd, args) {
  if (cmd.substr(0, 4) == "vote") return parseVote(event, cmd.substr(4), args);
  else {
    switch (cmd) {
      case 'source':
      case 'version':
        client.send(event.channel, 'VoteServ v' + VERSION + ' (standalone irc vote bot written in node.js) - Source: https://github.com/omnidan/VoteServ');
      break;
      case 'issue':
      case 'issues':
      case 'bug':
        client.send(event.channel, 'Please file issue requests here: https://github.com/omnidan/VoteServ/issues');
      break;
      case 'strip':
        client.send(event.channel, '*takes off its clothes* I\'m running on node v' + process.versions.node + ' with v8 v' + process.versions.v8);
      break;
      case 'who':
      case 'whovoted':
        if (args.length > 1) {
          // !who (voted) (to) ACTION USER
          if ((args.length > 2) && (args[0] == 'voted')) args.shift();
          // !whovoted (to) ACTION USER
          if ((args.length > 2) && (args[0] == 'to')) args.shift();

          // store vote with key ACTION_USER
          var votefor = args[0] + '_' + args[1];
          if (votes[votefor]) {
            var whovoted = votes[votefor].join(', ');
            client.send(event.user,
              'The following people voted to \x02' + args[0] + '\x02 \x02' +
              args[1] + '\x02: ' + whovoted +
              '. (Votes: \x02' + votes[votefor].length + '\x02)');
          } else client.send(event.channel ? event.channel : event.user,
            'No votes to \x02' + args[0] + '\x02 \x02' + args[1] + '\x02.');
        } else {
          client.send(event.channel ? event.channel : event.user,
            'Not enough arguments.');
        }
      break;
    }
    return;
  }
}

// parse channel messages
client.on('message', function(event) {
  if (event.message.substr(0, 1) == '!') { // prefix parsing
    var args = event.message.substr(1).split(' ');
    var cmd = args.shift();
    return parseCommand(event, cmd, args.length > 0 ? args : []);
  }
});

// parse private messages
client.on('privatemessage', function(event) {
  var args = event.message.split(' ');
  var cmd = args.shift();
  return parseCommand(event, cmd, args.length > 0 ? args : []);
});
<|endoftext|>


<commit_before>'use strict'

var utilities = require('../brain/utilities');
var config = require('../config/config');

// not needed?
// will delete this if won't cause problems when missing
// may be necessary if we want to verify that request actually coming from Slack
function verify() {
  console.log("Nothing to see here.")
}

function translateRequestToGenericFormats(context) {
  // do any other kinds of Request come from Slack?
  var genericRequests = [{
    reqType: 'user-input',
    userInput: '',
    context: context
  }];
  var text = context.userRequest.text;
  if (text) {
    genericRequests[0].userInput = text;
  }
  return genericRequests;
}
s
function generateResponsePayloads(genericResponse) {
  console.log("About to begin generating payloads from genericResponse.");
  // form basic payload - separate into function?
  var path = config.slackAccessToken;
  var uri = 'https://hooks.slack.com/services/' + path;
  var channel = genericResponse.context.userRequest.channel_id;
  var payloads =  [{
    uri: uri,
    method: 'POST',
    json: {
      channel: channel,
      username: 'GetHuman',
      icon_emoji: ':gethuman:',
      text: '',
      attachments: []
    }
  }];

// Case: no user input
  if (genericResponse.type === 'no-input') {
    console.log('No user input flag detected in genericResponse.');
    payloads[0].json.text = 'Tell me the company you would like to contact.';
    return payloads;
  }
// Case: nothing returned from Companies search / junk input
  else if (genericResponse.type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    payloads[0].json.text = 'I couldn\'t tell what you meant by \"' + genericResponse.userInput + '\". Please tell me company you are looking for. (ex: \"/gethuman Verizon Wireless\")';
    return payloads;
  }
  // do we need the explicit type check after the first two, or just 'else'?
  else if (genericResponse.type === 'standard') {
    console.log('Standard type flag detected in genericResponse.');
    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];
    var topContacts = formatTextField(genericResponse.data.contactMethods);
    var colors = utilities.colors;

  // get payload-loaders into sub-functions for testing
    if (posts && posts.length) {
        payloads[0].json.text = "Top issues for " + name + ":";
        for (let i = 0; i < posts.length; i++) {
            let title = posts[i].title || '';
            let urlId = posts[i].urlId || ''
            let color = colors[i];
            let singleAttachment = {
                "fallback": "Issue for " + name,
                "title": title,
                "color": color,
                "fields": [
                    {
                        "value": "<https://gethuman.com?company=" + encodeURIComponent(name) + "|Solve for me - $20>",
                        "short": true
                    },
                    {
                        "value": "<https://answers.gethuman.co/_" + encodeURIComponent(urlId) + "|More info ...>",
                        "short": true
                    }
                ]
            };
            payloads[0].json.attachments.push(singleAttachment);
        };
      console.log("Posts info pushed into Payloads");
    }

    // attach Company contact info:
    if (topContacts) {
      payloads[0].json.attachments.push({
          "fallback": "Contact info for " + name,
          "title": "Best ways to contact " + name + ":",
          "color": '#999999',
          "text": topContacts,
      });
      console.log("Company Contact Info pushed into Payloads");
    };

    // attach Other Companies info if they exist
    if (otherCompanies && otherCompanies.length) {
        var otherCompaniesList = convertArrayToBoldList(otherCompanies);
        payloads[0].json.attachments.push({
            "fallback": "Other solutions",
            "title": "Were you talking about " + name + "?",
            "color": '#BBBBBB',
            "text": "Or maybe you meant " + otherCompaniesList + "?",
            "mrkdwn_in": ["text"]
        });
        console.log("Other Companies info pushed into Payloads");
    }

    if (!payloads[0].json.attachments.length) {
        payloads[0].json.text = 'I couldn\'t find anything for \"' + name + '\". Please tell me which company you are looking for. (ex: \"/gethuman Verizon Wireless\")'
        console.log('No card info found for Companies, returning Nothing Found text.');
    }
    return payloads;
  }
}

function formatTextField(contactMethods) {
  var result = '';
  var counter = 1;
  for(var key in contactMethods) {
    if (contactMethods.hasOwnProperty(key) && (counter <= 3) && (contactMethods[key])) {
      switch(key) {
          case 'twitter':
              result = result + '<https://twitter.com/' + contactMethods[key] +'|Twitter> | ';
              break;
          case 'web':
              result = result + '<' + contactMethods[key] +'|Web> | ';
              break;
          case 'chat':
              result = result + '<' + contactMethods[key] +'|Chat> | ';
              break;
          case 'facebook':
              result = result + '<' + contactMethods[key] +'|Facebook> | ';
              break;
          default:
              result = result + contactMethods[key] + ' | ';
      }
      counter += 1;
    }
  }
  if (result) {
    result = result.slice(0,-3);
  }
  console.log("Formatted string for Slack contact methods: " + result);
  return result;
};

// convert an array of strings to one string separated by commas, with each entry *bolded*
function convertArrayToBoldList(arrayOfStrings) {
  var result = '*';
  result = result + arrayOfStrings.join('*, *') + "*";
  return result;
}

module.exports = {
  // sendResponseToPlatform: sendResponseToPlatform,
  // sendErrorResponse: sendErrorResponse,
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads
};
<commit_msg>debug<commit_after>'use strict'

var utilities = require('../brain/utilities');
var config = require('../config/config');

// not needed?
// will delete this if won't cause problems when missing
// may be necessary if we want to verify that request actually coming from Slack
function verify() {
  console.log("Nothing to see here.")
}

function translateRequestToGenericFormats(context) {
  // do any other kinds of Request come from Slack?
  var genericRequests = [{
    reqType: 'user-input',
    userInput: '',
    context: context
  }];
  var text = context.userRequest.text;
  if (text) {
    genericRequests[0].userInput = text;
  }
  return genericRequests;
}

function generateResponsePayloads(genericResponse) {
  console.log("About to begin generating payloads from genericResponse.");
  // form basic payload - separate into function?
  var path = config.slackAccessToken;
  var uri = 'https://hooks.slack.com/services/' + path;
  var channel = genericResponse.context.userRequest.channel_id;
  var payloads =  [{
    uri: uri,
    method: 'POST',
    json: {
      channel: channel,
      username: 'GetHuman',
      icon_emoji: ':gethuman:',
      text: '',
      attachments: []
    }
  }];

// Case: no user input
  if (genericResponse.type === 'no-input') {
    console.log('No user input flag detected in genericResponse.');
    payloads[0].json.text = 'Tell me the company you would like to contact.';
    return payloads;
  }
// Case: nothing returned from Companies search / junk input
  else if (genericResponse.type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    payloads[0].json.text = 'I couldn\'t tell what you meant by \"' + genericResponse.userInput + '\". Please tell me company you are looking for. (ex: \"/gethuman Verizon Wireless\")';
    return payloads;
  }
  // do we need the explicit type check after the first two, or just 'else'?
  else if (genericResponse.type === 'standard') {
    console.log('Standard type flag detected in genericResponse.');
    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];
    var topContacts = formatTextField(genericResponse.data.contactMethods);
    var colors = utilities.colors;

  // get payload-loaders into sub-functions for testing
    if (posts && posts.length) {
        payloads[0].json.text = "Top issues for " + name + ":";
        for (let i = 0; i < posts.length; i++) {
            let title = posts[i].title || '';
            let urlId = posts[i].urlId || ''
            let color = colors[i];
            let singleAttachment = {
                "fallback": "Issue for " + name,
                "title": title,
                "color": color,
                "fields": [
                    {
                        "value": "<https://gethuman.com?company=" + encodeURIComponent(name) + "|Solve for me - $20>",
                        "short": true
                    },
                    {
                        "value": "<https://answers.gethuman.co/_" + encodeURIComponent(urlId) + "|More info ...>",
                        "short": true
                    }
                ]
            };
            payloads[0].json.attachments.push(singleAttachment);
        };
      console.log("Posts info pushed into Payloads");
    }

    // attach Company contact info:
    if (topContacts) {
      payloads[0].json.attachments.push({
          "fallback": "Contact info for " + name,
          "title": "Best ways to contact " + name + ":",
          "color": '#999999',
          "text": topContacts,
      });
      console.log("Company Contact Info pushed into Payloads");
    };

    // attach Other Companies info if they exist
    if (otherCompanies && otherCompanies.length) {
        var otherCompaniesList = convertArrayToBoldList(otherCompanies);
        payloads[0].json.attachments.push({
            "fallback": "Other solutions",
            "title": "Were you talking about " + name + "?",
            "color": '#BBBBBB',
            "text": "Or maybe you meant " + otherCompaniesList + "?",
            "mrkdwn_in": ["text"]
        });
        console.log("Other Companies info pushed into Payloads");
    }

    if (!payloads[0].json.attachments.length) {
        payloads[0].json.text = 'I couldn\'t find anything for \"' + name + '\". Please tell me which company you are looking for. (ex: \"/gethuman Verizon Wireless\")'
        console.log('No card info found for Companies, returning Nothing Found text.');
    }
    return payloads;
  }
}

function formatTextField(contactMethods) {
  var result = '';
  var counter = 1;
  for(var key in contactMethods) {
    if (contactMethods.hasOwnProperty(key) && (counter <= 3) && (contactMethods[key])) {
      switch(key) {
          case 'twitter':
              result = result + '<https://twitter.com/' + contactMethods[key] +'|Twitter> | ';
              break;
          case 'web':
              result = result + '<' + contactMethods[key] +'|Web> | ';
              break;
          case 'chat':
              result = result + '<' + contactMethods[key] +'|Chat> | ';
              break;
          case 'facebook':
              result = result + '<' + contactMethods[key] +'|Facebook> | ';
              break;
          default:
              result = result + contactMethods[key] + ' | ';
      }
      counter += 1;
    }
  }
  if (result) {
    result = result.slice(0,-3);
  }
  console.log("Formatted string for Slack contact methods: " + result);
  return result;
};

// convert an array of strings to one string separated by commas, with each entry *bolded*
function convertArrayToBoldList(arrayOfStrings) {
  var result = '*';
  result = result + arrayOfStrings.join('*, *') + "*";
  return result;
}

module.exports = {
  // sendResponseToPlatform: sendResponseToPlatform,
  // sendErrorResponse: sendErrorResponse,
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads
};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import {
  TouchableNativeFeedback,
  TouchableHighlight,
  StyleSheet,
  View,
  Platform,
  ActivityIndicator,
  Text as NativeText,
} from 'react-native';
import colors from '../config/colors';
import Text from '../text/Text';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import getIconType from '../helpers/getIconType';
import normalize from '../helpers/normalizeText';

const log = () => {
  console.log('please attach method to this component'); //eslint-disable-line no-console
};

const Button = props => {
  const {
    disabled,
    loading,
    loadingRight,
    activityIndicatorStyle,
    buttonStyle,
    borderRadius,
    title,
    onPress,
    icon,
    secondary,
    secondary2,
    secondary3,
    primary1,
    primary2,
    backgroundColor,
    color,
    fontSize,
    underlayColor,
    raised,
    textStyle,
    large,
    iconRight,
    fontWeight,
    disabledStyle,
    fontFamily,
    containerViewStyle,
    ...attributes
  } = props;
  let { Component } = props;

  let iconElement;
  if (icon) {
    let Icon;
    if (!icon.type) {
      Icon = MaterialIcon;
    } else {
      Icon = getIconType(icon.type);
    }
    iconElement = (
      <Icon
        color={icon.color || 'white'}
        size={icon.size || (large ? 26 : 18)}
        style={[
          iconRight ? styles.iconRight : styles.icon,
          icon.style && icon.style,
        ]}
        name={icon.name}
      />
    );
  }
  let loadingElement;
  if (loading) {
    loadingElement = (
      <ActivityIndicator
        animating={true}
        style={[styles.activityIndicatorStyle, activityIndicatorStyle]}
        color={color || 'white'}
        size={(large && 'large') || 'small'}
      />
    );
  }
  if (!Component && Platform.OS === 'ios') {
    Component = TouchableHighlight;
  }
  if (!Component && Platform.OS === 'android') {
    Component = TouchableNativeFeedback;
  }
  if (!Component) {
    Component = TouchableHighlight;
  }

  if (
    containerViewStyle &&
    containerViewStyle.borderRadius &&
    !attributes.background
  ) {
    attributes.background = TouchableNativeFeedback.Ripple(
      'ThemeAttrAndroid',
      true
    );
  }

  return (
    <View
      style={[styles.container, raised && styles.raised, containerViewStyle]}
    >
      <Component
        underlayColor={underlayColor || 'transparent'}
        onPress={onPress || log}
        disabled={disabled || false}
        {...attributes}
      >
        <View
          style={[
            styles.button,
            secondary && { backgroundColor: colors.secondary },
            secondary2 && { backgroundColor: colors.secondary2 },
            secondary3 && { backgroundColor: colors.secondary3 },
            primary1 && { backgroundColor: colors.primary1 },
            primary2 && { backgroundColor: colors.primary2 },
            backgroundColor && { backgroundColor: backgroundColor },
            borderRadius && { borderRadius },
            !large && styles.small,
            buttonStyle && buttonStyle,
            disabled && { backgroundColor: colors.disabled },
            disabled && disabledStyle && disabledStyle,
          ]}
        >
          {icon && !iconRight && iconElement}
          {loading && !loadingRight && loadingElement}
          <Text
            style={[
              styles.text,
              color && { color },
              !large && styles.smallFont,
              fontSize && { fontSize },
              textStyle && textStyle,
              fontWeight && { fontWeight },
              fontFamily && { fontFamily },
            ]}
          >
            {title}
          </Text>
          {loading && loadingRight && loadingElement}
          {icon && iconRight && iconElement}
        </View>
      </Component>
    </View>
  );
};

Button.propTypes = {
  buttonStyle: View.propTypes.style,
  title: PropTypes.string,
  onPress: PropTypes.any,
  icon: PropTypes.object,
  secondary: PropTypes.bool,
  secondary2: PropTypes.bool,
  secondary3: PropTypes.bool,
  primary1: PropTypes.bool,
  primary2: PropTypes.bool,
  backgroundColor: PropTypes.string,
  color: PropTypes.string,
  fontSize: PropTypes.any,
  underlayColor: PropTypes.string,
  raised: PropTypes.bool,
  textStyle: NativeText.propTypes.style,
  disabled: PropTypes.bool,
  loading: PropTypes.bool,
  activityIndicatorStyle: View.propTypes.style,
  loadingRight: PropTypes.bool,
  Component: PropTypes.any,
  borderRadius: PropTypes.number,
  large: PropTypes.bool,
  iconRight: PropTypes.bool,
  fontWeight: PropTypes.string,
  disabledStyle: View.propTypes.style,
  fontFamily: PropTypes.string,
};

const styles = StyleSheet.create({
  container: {
    marginLeft: 15,
    marginRight: 15,
  },
  button: {
    padding: 19,
    backgroundColor: colors.primary,
    justifyContent: 'center',
    alignItems: 'center',
    flexDirection: 'row',
  },
  text: {
    color: 'white',
    fontSize: normalize(16),
  },
  icon: {
    marginRight: 10,
  },
  iconRight: {
    marginLeft: 10,
  },
  small: {
    padding: 12,
  },
  smallFont: {
    fontSize: normalize(14),
  },
  activityIndicatorStyle: {
    marginHorizontal: 10,
    height: 0,
  },
  raised: {
    ...Platform.select({
      ios: {
        shadowColor: 'rgba(0,0,0, .4)',
        shadowOffset: { height: 1, width: 1 },
        shadowOpacity: 1,
        shadowRadius: 1,
      },
      android: {
        elevation: 2,
      },
    }),
  },
});

export default Button;
<commit_msg>just check for borderRadius prop<commit_after>import React, { PropTypes } from 'react';
import {
  TouchableNativeFeedback,
  TouchableHighlight,
  StyleSheet,
  View,
  Platform,
  ActivityIndicator,
  Text as NativeText,
} from 'react-native';
import colors from '../config/colors';
import Text from '../text/Text';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import getIconType from '../helpers/getIconType';
import normalize from '../helpers/normalizeText';

const log = () => {
  console.log('please attach method to this component'); //eslint-disable-line no-console
};

const Button = props => {
  const {
    disabled,
    loading,
    loadingRight,
    activityIndicatorStyle,
    buttonStyle,
    borderRadius,
    title,
    onPress,
    icon,
    secondary,
    secondary2,
    secondary3,
    primary1,
    primary2,
    backgroundColor,
    color,
    fontSize,
    underlayColor,
    raised,
    textStyle,
    large,
    iconRight,
    fontWeight,
    disabledStyle,
    fontFamily,
    containerViewStyle,
    ...attributes
  } = props;
  let { Component } = props;

  let iconElement;
  if (icon) {
    let Icon;
    if (!icon.type) {
      Icon = MaterialIcon;
    } else {
      Icon = getIconType(icon.type);
    }
    iconElement = (
      <Icon
        color={icon.color || 'white'}
        size={icon.size || (large ? 26 : 18)}
        style={[
          iconRight ? styles.iconRight : styles.icon,
          icon.style && icon.style,
        ]}
        name={icon.name}
      />
    );
  }
  let loadingElement;
  if (loading) {
    loadingElement = (
      <ActivityIndicator
        animating={true}
        style={[styles.activityIndicatorStyle, activityIndicatorStyle]}
        color={color || 'white'}
        size={(large && 'large') || 'small'}
      />
    );
  }
  if (!Component && Platform.OS === 'ios') {
    Component = TouchableHighlight;
  }
  if (!Component && Platform.OS === 'android') {
    Component = TouchableNativeFeedback;
  }
  if (!Component) {
    Component = TouchableHighlight;
  }

  if (borderRadius && !attributes.background) {
    attributes.background = TouchableNativeFeedback.Ripple(
      'ThemeAttrAndroid',
      true
    );
  }

  return (
    <View
      style={[styles.container, raised && styles.raised, containerViewStyle]}
    >
      <Component
        underlayColor={underlayColor || 'transparent'}
        onPress={onPress || log}
        disabled={disabled || false}
        {...attributes}
      >
        <View
          style={[
            styles.button,
            secondary && { backgroundColor: colors.secondary },
            secondary2 && { backgroundColor: colors.secondary2 },
            secondary3 && { backgroundColor: colors.secondary3 },
            primary1 && { backgroundColor: colors.primary1 },
            primary2 && { backgroundColor: colors.primary2 },
            backgroundColor && { backgroundColor: backgroundColor },
            borderRadius && { borderRadius },
            !large && styles.small,
            buttonStyle && buttonStyle,
            disabled && { backgroundColor: colors.disabled },
            disabled && disabledStyle && disabledStyle,
          ]}
        >
          {icon && !iconRight && iconElement}
          {loading && !loadingRight && loadingElement}
          <Text
            style={[
              styles.text,
              color && { color },
              !large && styles.smallFont,
              fontSize && { fontSize },
              textStyle && textStyle,
              fontWeight && { fontWeight },
              fontFamily && { fontFamily },
            ]}
          >
            {title}
          </Text>
          {loading && loadingRight && loadingElement}
          {icon && iconRight && iconElement}
        </View>
      </Component>
    </View>
  );
};

Button.propTypes = {
  buttonStyle: View.propTypes.style,
  title: PropTypes.string,
  onPress: PropTypes.any,
  icon: PropTypes.object,
  secondary: PropTypes.bool,
  secondary2: PropTypes.bool,
  secondary3: PropTypes.bool,
  primary1: PropTypes.bool,
  primary2: PropTypes.bool,
  backgroundColor: PropTypes.string,
  color: PropTypes.string,
  fontSize: PropTypes.any,
  underlayColor: PropTypes.string,
  raised: PropTypes.bool,
  textStyle: NativeText.propTypes.style,
  disabled: PropTypes.bool,
  loading: PropTypes.bool,
  activityIndicatorStyle: View.propTypes.style,
  loadingRight: PropTypes.bool,
  Component: PropTypes.any,
  borderRadius: PropTypes.number,
  large: PropTypes.bool,
  iconRight: PropTypes.bool,
  fontWeight: PropTypes.string,
  disabledStyle: View.propTypes.style,
  fontFamily: PropTypes.string,
};

const styles = StyleSheet.create({
  container: {
    marginLeft: 15,
    marginRight: 15,
  },
  button: {
    padding: 19,
    backgroundColor: colors.primary,
    justifyContent: 'center',
    alignItems: 'center',
    flexDirection: 'row',
  },
  text: {
    color: 'white',
    fontSize: normalize(16),
  },
  icon: {
    marginRight: 10,
  },
  iconRight: {
    marginLeft: 10,
  },
  small: {
    padding: 12,
  },
  smallFont: {
    fontSize: normalize(14),
  },
  activityIndicatorStyle: {
    marginHorizontal: 10,
    height: 0,
  },
  raised: {
    ...Platform.select({
      ios: {
        shadowColor: 'rgba(0,0,0, .4)',
        shadowOffset: { height: 1, width: 1 },
        shadowOpacity: 1,
        shadowRadius: 1,
      },
      android: {
        elevation: 2,
      },
    }),
  },
});

export default Button;
<|endoftext|>


<commit_before>var Immutable = require('immutable');
var NONE = 0;
var PIECE = 1;
var EMPTY = 2;

var mainBoard = Immutable.fromJS([
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
]);
var frenchBoard = Immutable.fromJS([
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, PIECE, PIECE, PIECE, PIECE, PIECE, NONE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [NONE, PIECE, PIECE, PIECE, PIECE, PIECE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
]);
var gameStatus = frenchBoard;
gameStatus = dig(gameStatus, 3, 3);
console.log(solve(gameStatus, getPieces(gameStatus)));
function solve(board, piece) {
    if (piece === 1) {
        return [];
    }
    var status = board;
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            if (board.getIn([i, j]) !== PIECE) {
                continue;
            }
            var possibleDirection = getPossibleDirection(board, j, i);
            var directions = ['left', 'right', 'up', 'down'];
            for (var d = 0, _d = directions.length; d < _d; d = 0 | d + 1) {
                if (!possibleDirection[directions[d]]) {
                    continue;
                }
                var res = solve(move(board, j, i, directions[d]), piece - 1);
                if (!Immutable.List.isList(res)) {
                    // succeeded
                    res.push(['(' + j + ', ' + i + ')', directions[d]]);
                    return res;
                }
            }
        }
    }
    return board;
}
function getPossibleDirection(board, a, b) {
    var possibleDirection = {
        left: false,
        right: false,
        up: false,
        down: false
    };
    if (board.getIn([b, a]) !== PIECE) return possibleDirection;
    var width = board.get(0).size;
    var height = board.size;
    if (a - 2 >= 0 &&
        board.getIn([b, a - 1]) === PIECE && board.getIn([b, a - 2]) === EMPTY)
         possibleDirection.left = true;

    if (a + 2 < width &&
        board.getIn([b, a + 1]) === PIECE && board.getIn([b, a + 2]) === EMPTY)
         possibleDirection.right = true;

    if (b - 2 >= 0 &&
        board.getIn([b - 1, a]) === PIECE && board.getIn([b - 2, a]) === EMPTY)
         possibleDirection.up = true;

    if (b + 2 < height &&
        board.getIn([b + 1, a]) === PIECE && board.getIn([b + 2, a]) === EMPTY)
         possibleDirection.down = true;

    return possibleDirection;
}
function move(board, a, b, direction) {
    var possibleDirection = getPossibleDirection(board, a, b);
    var res = board;
    if (possibleDirection[direction] === false) return false; // cannot move
    res = res.setIn([b, a], EMPTY);
    if (direction === 'left') {
        res = res.setIn([b, a - 1], EMPTY);
        res = res.setIn([b, a - 2], PIECE);
    }
    if (direction === 'right') {
        res = res.setIn([b, a + 1], EMPTY);
        res = res.setIn([b, a + 2], PIECE);
    }
    if (direction === 'up') {
        res = res.setIn([b - 1, a], EMPTY);
        res = res.setIn([b - 2, a], PIECE);
    }
    if (direction === 'down') {
        res = res.setIn([b + 1, a], EMPTY);
        res = res.setIn([b + 2, a], PIECE);
    }
    return res;
}
function dig(board, a, b) {
    return board.setIn([b, a], EMPTY);
}
function getPieces(board) {
    var piece = 0;
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            if (board.getIn([i, j]) === PIECE) piece = 0 | piece + 1;
        }
    }
    return piece;
}
function showBoard(board) {
    var res = '';
    var status = [' ■', ' O', '  '];
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            res += status[board.getIn([i, j])];
        }
        res += '\n';
    }
    return res;
}
<commit_msg>rename mainBoard to englishBoard<commit_after>var Immutable = require('immutable');
var NONE = 0;
var PIECE = 1;
var EMPTY = 2;

var englishBoard = Immutable.fromJS([
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
]);
var frenchBoard = Immutable.fromJS([
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
    [NONE, PIECE, PIECE, PIECE, PIECE, PIECE, NONE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [PIECE, PIECE, PIECE, PIECE, PIECE, PIECE, PIECE],
    [NONE, PIECE, PIECE, PIECE, PIECE, PIECE, NONE],
    [NONE, NONE, PIECE, PIECE, PIECE, NONE, NONE],
]);
var gameStatus = frenchBoard;
gameStatus = dig(gameStatus, 3, 3);
console.log(solve(gameStatus, getPieces(gameStatus)));
function solve(board, piece) {
    if (piece === 1) {
        return [];
    }
    var status = board;
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            if (board.getIn([i, j]) !== PIECE) {
                continue;
            }
            var possibleDirection = getPossibleDirection(board, j, i);
            var directions = ['left', 'right', 'up', 'down'];
            for (var d = 0, _d = directions.length; d < _d; d = 0 | d + 1) {
                if (!possibleDirection[directions[d]]) {
                    continue;
                }
                var res = solve(move(board, j, i, directions[d]), piece - 1);
                if (!Immutable.List.isList(res)) {
                    // succeeded
                    res.push(['(' + j + ', ' + i + ')', directions[d]]);
                    return res;
                }
            }
        }
    }
    return board;
}
function getPossibleDirection(board, a, b) {
    var possibleDirection = {
        left: false,
        right: false,
        up: false,
        down: false
    };
    if (board.getIn([b, a]) !== PIECE) return possibleDirection;
    var width = board.get(0).size;
    var height = board.size;
    if (a - 2 >= 0 &&
        board.getIn([b, a - 1]) === PIECE && board.getIn([b, a - 2]) === EMPTY)
         possibleDirection.left = true;

    if (a + 2 < width &&
        board.getIn([b, a + 1]) === PIECE && board.getIn([b, a + 2]) === EMPTY)
         possibleDirection.right = true;

    if (b - 2 >= 0 &&
        board.getIn([b - 1, a]) === PIECE && board.getIn([b - 2, a]) === EMPTY)
         possibleDirection.up = true;

    if (b + 2 < height &&
        board.getIn([b + 1, a]) === PIECE && board.getIn([b + 2, a]) === EMPTY)
         possibleDirection.down = true;

    return possibleDirection;
}
function move(board, a, b, direction) {
    var possibleDirection = getPossibleDirection(board, a, b);
    var res = board;
    if (possibleDirection[direction] === false) return false; // cannot move
    res = res.setIn([b, a], EMPTY);
    if (direction === 'left') {
        res = res.setIn([b, a - 1], EMPTY);
        res = res.setIn([b, a - 2], PIECE);
    }
    if (direction === 'right') {
        res = res.setIn([b, a + 1], EMPTY);
        res = res.setIn([b, a + 2], PIECE);
    }
    if (direction === 'up') {
        res = res.setIn([b - 1, a], EMPTY);
        res = res.setIn([b - 2, a], PIECE);
    }
    if (direction === 'down') {
        res = res.setIn([b + 1, a], EMPTY);
        res = res.setIn([b + 2, a], PIECE);
    }
    return res;
}
function dig(board, a, b) {
    return board.setIn([b, a], EMPTY);
}
function getPieces(board) {
    var piece = 0;
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            if (board.getIn([i, j]) === PIECE) piece = 0 | piece + 1;
        }
    }
    return piece;
}
function showBoard(board) {
    var res = '';
    var status = [' ■', ' O', '  '];
    for (var i = 0, _i = board.size; i < _i; i = 0 | i + 1) {
        for (var j = 0, _j = board.get(i).size; j < _j; j = 0 | j + 1) {
            res += status[board.getIn([i, j])];
        }
        res += '\n';
    }
    return res;
}
<|endoftext|>


<commit_before>const electron = require('electron');
const { app, BrowserWindow, clipboard, shell, globalShortcut, ipcMain, Menu, Tray, nativeImage } = require('electron');
const _ = require('lodash');
const path = require('path');
const url = require('url');
const fixPath = require('fix-path');
const defaultMenu = require('electron-default-menu');

fixPath();

const config = require('./application/SettingsFile');

const ChannelPlay = require('./application/ChannelPlay');
const TrayIcon = require('./application/TrayIcon');
const Logger = require('./application/Logger');

require('./application/ChannelCheck');
require('./application/Import');
require('./application/ChannelInfo');
require('./application/VersionCheck');

const clientVersion = require('./package.json').version;

const isDev = process.env.NODE_ENV === 'dev';

console.log('isDev', isDev);

let forceQuit = false;

ipcMain.once('client_ready', () => {
  console.log('client ready.');
});

let iconPath = path.normalize(path.join(__dirname, 'icons', 'icon.png'));
let iconPathTray = path.normalize(path.join(__dirname, 'icons', 'icon32.png'));
let iconPathBalloon = path.normalize(path.join(__dirname, 'icons', 'icon.png'));

if (process.platform === 'darwin') {
  app.dock.setIcon(iconPath);
  app.dock.hide();

  iconPathTray = path.normalize(path.join(__dirname, 'icons', 'iconTemplate.png'));
}

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

app.setName('Kolpaque Client');

function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    title: 'Kolpaque Client',
    minWidth: 300,
    minHeight: 400,
    width: config.settings.size[0],
    height: config.settings.size[1],
    resizable: true,
    fullscreenable: false,
    icon: iconPath
  });

  app.mainWindow = mainWindow;

  mainWindow.setMenu(null);

  // and load the index.html of the app.
  if (isDev) {
    const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer');

    mainWindow.loadURL('http://localhost:3000');

    // Open the DevTools.
    mainWindow.webContents.openDevTools();
    installExtension(REACT_DEVELOPER_TOOLS)
      .then(name => console.log('Extension added', name))
      .catch(err => console.log('An error occurred', err));
    installExtension(REDUX_DEVTOOLS)
      .then(name => console.log('Extension added', name))
      .catch(err => console.log('An error occurred', err));
  } else {
    mainWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, 'dist/index.html'),
        protocol: 'file:',
        slashes: true
      })
    );
  }

  mainWindow.on('minimize', function() {
    mainWindow.hide();
  });

  mainWindow.on('close', function() {
    config.saveFile();
  });

  mainWindow.on('close', function(e) {
    console.log('forceQuit', forceQuit);

    if (forceQuit) return;

    if (process.platform === 'darwin') {
      e.preventDefault();
      mainWindow.hide();
    }
  });

  mainWindow.on('resize', function() {
    config.settings.size = mainWindow.getSize();
  });

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.

    mainWindow = null;
  });
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q

  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', function() {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow();
  }
});

app.on('ready', function() {
  if (!config.settings.minimizeAtStart) return;

  mainWindow.hide();
});

let contextMenuTemplate = [
  {
    label: 'Toggle Client',
    type: 'normal',
    visible: process.platform === 'linux',
    click: () => {
      mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
    }
  },
  {
    label: 'Online Channels',
    type: 'submenu',
    submenu: []
  },
  {
    label: 'Play / Last Closed',
    type: 'normal',
    visible: false,
    click: () => {}
  },
  {
    label: 'Play / Clipboard',
    type: 'normal',
    click: (menuItem, browserWindow, event) => {
      ChannelPlay.launchPlayerLink(clipboard.readText(), event.ctrlKey);
    }
  },
  {
    label: 'Notifications',
    type: 'checkbox',
    click: menuItem => {
      console.log('menuItem.checked', menuItem.checked);
      config.changeSetting('showNotifications', menuItem.checked);
    },
    checked: config.settings.showNotifications
  },
  {
    label: 'Quit Client',
    type: 'normal',
    click: () => {
      forceQuit = true;
      app.quit();
    }
  }
];

app.contextMenuTemplate = contextMenuTemplate;

let appIcon;
app.on('ready', () => {
  appIcon = new Tray(nativeImage.createFromPath(iconPathTray));
  appIcon.setToolTip('Kolpaque Client');
  appIcon.iconPathBalloon = iconPathBalloon;

  appIcon.on('click', () => {
    console.log('left-click event.');
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });

  appIcon.on('right-click', () => {
    console.log('right-click event.');
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });

  app.appIcon = appIcon;

  TrayIcon.rebuildIconMenu();

  if (process.platform === 'darwin') {
    const menu = defaultMenu(app, shell);

    Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
  }
});

process.on('uncaughtException', function(err) {
  console.log('Caught exception: ' + err.stack);

  Logger(err.stack);
});
<commit_msg>Style fix.<commit_after>const electron = require('electron');
const { app, BrowserWindow, clipboard, shell, globalShortcut, ipcMain, Menu, Tray, nativeImage } = require('electron');
const _ = require('lodash');
const path = require('path');
const url = require('url');
const fixPath = require('fix-path');
const defaultMenu = require('electron-default-menu');

fixPath();

const config = require('./application/SettingsFile');

const ChannelPlay = require('./application/ChannelPlay');
const TrayIcon = require('./application/TrayIcon');
const Logger = require('./application/Logger');

require('./application/ChannelCheck');
require('./application/Import');
require('./application/ChannelInfo');
require('./application/VersionCheck');

const isDev = process.env.NODE_ENV === 'dev';

console.log('isDev', isDev);

let forceQuit = false;

ipcMain.once('client_ready', () => {
  console.log('client ready.');
});

let iconPath = path.normalize(path.join(__dirname, 'icons', 'icon.png'));
let iconPathTray = path.normalize(path.join(__dirname, 'icons', 'icon32.png'));
let iconPathBalloon = path.normalize(path.join(__dirname, 'icons', 'icon.png'));

if (process.platform === 'darwin') {
  app.dock.setIcon(iconPath);
  app.dock.hide();

  iconPathTray = path.normalize(path.join(__dirname, 'icons', 'iconTemplate.png'));
}

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

app.setName('Kolpaque Client');

function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    title: 'Kolpaque Client',
    minWidth: 300,
    minHeight: 400,
    width: config.settings.size[0],
    height: config.settings.size[1],
    resizable: true,
    fullscreenable: false,
    icon: iconPath
  });

  app.mainWindow = mainWindow;

  mainWindow.setMenu(null);

  // and load the index.html of the app.
  if (isDev) {
    const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer');

    mainWindow.loadURL('http://localhost:3000');

    mainWindow.webContents.openDevTools();

    installExtension(REACT_DEVELOPER_TOOLS)
      .then(name => console.log('Extension added', name))
      .catch(err => console.log('An error occurred', err));
    installExtension(REDUX_DEVTOOLS)
      .then(name => console.log('Extension added', name))
      .catch(err => console.log('An error occurred', err));
  } else {
    mainWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, 'dist/index.html'),
        protocol: 'file:',
        slashes: true
      })
    );
  }

  mainWindow.on('minimize', function() {
    mainWindow.hide();
  });

  mainWindow.on('close', function() {
    config.saveFile();
  });

  mainWindow.on('close', function(e) {
    console.log('forceQuit', forceQuit);

    if (forceQuit) return;

    if (process.platform === 'darwin') {
      e.preventDefault();
      mainWindow.hide();
    }
  });

  mainWindow.on('resize', function() {
    config.settings.size = mainWindow.getSize();
  });

  mainWindow.on('closed', function() {
    mainWindow = null;
  });
}

app.on('ready', createWindow);

app.on('window-all-closed', function() {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', function() {
  if (mainWindow === null) {
    createWindow();
  }
});

app.on('ready', function() {
  if (!config.settings.minimizeAtStart) return;

  mainWindow.hide();
});

let contextMenuTemplate = [
  {
    label: 'Toggle Client',
    type: 'normal',
    visible: process.platform === 'linux',
    click: () => {
      mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
    }
  },
  {
    label: 'Online Channels',
    type: 'submenu',
    submenu: []
  },
  {
    label: 'Play / Last Closed',
    type: 'normal',
    visible: false,
    click: () => {}
  },
  {
    label: 'Play / Clipboard',
    type: 'normal',
    click: (menuItem, browserWindow, event) => {
      ChannelPlay.launchPlayerLink(clipboard.readText(), event.ctrlKey);
    }
  },
  {
    label: 'Notifications',
    type: 'checkbox',
    click: menuItem => {
      console.log('menuItem.checked', menuItem.checked);
      config.changeSetting('showNotifications', menuItem.checked);
    },
    checked: config.settings.showNotifications
  },
  {
    label: 'Quit Client',
    type: 'normal',
    click: () => {
      forceQuit = true;
      app.quit();
    }
  }
];

app.contextMenuTemplate = contextMenuTemplate;

let appIcon;
app.on('ready', () => {
  appIcon = new Tray(nativeImage.createFromPath(iconPathTray));
  appIcon.setToolTip('Kolpaque Client');
  appIcon.iconPathBalloon = iconPathBalloon;

  appIcon.on('click', () => {
    console.log('left-click event.');
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });

  appIcon.on('right-click', () => {
    console.log('right-click event.');
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });

  app.appIcon = appIcon;

  TrayIcon.rebuildIconMenu();

  if (process.platform === 'darwin') {
    const menu = defaultMenu(app, shell);

    Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
  }
});

process.on('uncaughtException', function(err) {
  console.log('Caught exception: ' + err.stack);

  Logger(err.stack);
});
<|endoftext|>


<commit_before>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.
var Tray = require('tray');  // Module to create native browser window.

// Report crashes to our server.
require('crash-reporter').start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is GCed.
var mainWindow = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform != 'darwin') {
    app.quit();
  }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  // Create the browser window.
  mainWindow = new BrowserWindow({width: 800, height: 900, icon: 'stats100.png'});
  //mainWindow = new BrowserWindow({width: 570, height: 477, icon: 'stats100.png'});
  var appIcon = new Tray('stats100.png');
  appIcon.setTitle('Futures');

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // Open the devtools.
  mainWindow.openDevTools();

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});
<commit_msg>build up a context menu for the tray<commit_after>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.
var Tray = require('tray');  // Module to create native browser window.
var Menu = require('menu');

// Report crashes to our server.
require('crash-reporter').start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is GCed.
var mainWindow = null;
var appIcon = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform != 'darwin') {
    app.quit();
  }
});

var logToBrowser = function() {
if (mainWindow && mainWindow !== null) {
var baseArgs = ['console.log']
mainWindow.webContents.send.apply(mainWindow.webContents, baseArgs.concat([].slice.call(arguments)))
}
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  // Create the browser window.
  //mainWindow = new BrowserWindow({width: 800, height: 900, icon: 'stats100.png'});
  mainWindow = new BrowserWindow({
    width: 800,
    // height: 650,
    height: 900,
    icon: 'stats100.png',
	center: true,
	'skip-taskbar': true,
	frame: false,
	show: false
  });
  appIcon = new Tray('stats100.png');
  appIcon.setTitle('Futures');
  //var contextMenu = new Menu();
  //contextMenu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));

  var contextMenu = Menu.buildFromTemplate([
    { label: 'Show/Hide Venmo',
      //type: 'radio',
      click: function(){
		if (mainWindow.isVisible()) {
		  mainWindow.hide()
		} else {
		  //mainWindow.setPosition(parseInt(bounds.x + (bounds.width / 2) - 400), bounds.y + bounds.height)
		  mainWindow.show()
		}
      }
    },
  ]);
  //appIcon.setToolTip('This is my application.');
  appIcon.setContextMenu(contextMenu);

  appIcon.on('clicked', function(e, bounds) {
    logToBrowser('app icon clicked', e)
    logToBrowser('app icon clicked', bounds)
    console.log(bounds)
    if (mainWindow.isVisible()) {
      mainWindow.hide()
    } else {
      mainWindow.setPosition(parseInt(bounds.x + (bounds.width / 2) - 400), bounds.y + bounds.height)
      mainWindow.show()
    }
  })

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // Open the devtools.
  mainWindow.openDevTools();

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});
<|endoftext|>


<commit_before>const IP = "127.0.0.1"
const PORT = 8080;

// Enum of requests
var requestType = {
	NullRequest : 0,
	Handshake : 1,
	GameData : 2
};

var socketId;

chrome.sockets.tcp.create({}, function(createInfo) {
	socketId = createInfo.socketId;
  	chrome.sockets.tcp.connect(createInfo.socketId, IP, PORT, onConnectedCallback);
});

function onConnectedCallback() {
	console.log("Connected");

	chrome.sockets.tcp.onReceiveError.addListener(function(info) {
    	console.log("Error: ", info);
 	});

 	sendHandshake();

 	chrome.sockets.tcp.setPaused(info.clientSocketId, false);
}

function sendHandshake() {
	var handshake = {
  		Request_type: requestType.Handshake,
  		maxPlayers: 1,
  		minPlayers: 1,
  		Buttons: {
  			Width: 2,
  			Height: 2
  		},
  		Media: [{
  			Path: "ASKOASK",
  			Type: 0
  		}]
	}

	var json = JSON.stringify(handshake);
	console.log(json);
	buffer = str2ab(json);

	string2ArrayBuffer(json, function(buf) {
		chrome.sockets.tcp.send(socketId, buf, function(info) {
			if (info.resultCode != 0) {
      			console.log("Send failed.");
			}
		});
	});
}

chrome.sockets.tcp.onReceive.addListener(function(info) {
	console.log("Received data")
  	if (info.socketId != socketId)
    	return;
  	// info.data is an arrayBuffer.
  	console.log(info.data);
});

function string2ArrayBuffer(string, callback) {
    var blob = new Blob([string]);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result);
    }
    f.readAsArrayBuffer(blob);
}

function ab2str(buf) {
	return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
    	bufView[i] = str.charCodeAt(i);
    }

    return buf;
}<commit_msg>Removed unused string to byte conversion functions<commit_after>const IP = "127.0.0.1"
const PORT = 8080;

// Enum of requests
var requestType = {
	NullRequest : 0,
	Handshake : 1,
	GameData : 2
};

var socketId;

chrome.sockets.tcp.create({}, function(createInfo) {
	socketId = createInfo.socketId;
  	chrome.sockets.tcp.connect(createInfo.socketId, IP, PORT, onConnectedCallback);
});

function onConnectedCallback() {
	console.log("Connected");

	chrome.sockets.tcp.onReceiveError.addListener(function(info) {
    	console.log("Error: ", info);
 	});

 	sendHandshake();

 	chrome.sockets.tcp.setPaused(info.clientSocketId, false);
}

function sendHandshake() {
	var handshake = {
  		Request_type: requestType.Handshake,
  		maxPlayers: 1,
  		minPlayers: 1,
  		Buttons: {
  			Width: 2,
  			Height: 2
  		},
  		Media: [{
  			Path: "ASKOASK",
  			Type: 0
  		}]
	}

	var json = JSON.stringify(handshake);
	console.log(json);

	string2ArrayBuffer(json, function(buf) {
		chrome.sockets.tcp.send(socketId, buf, function(info) {
			if (info.resultCode != 0) {
      			console.log("Send failed.");
			}
		});
	});
}

chrome.sockets.tcp.onReceive.addListener(function(info) {
	console.log("Received data")
  	if (info.socketId != socketId)
    	return;
  	// info.data is an arrayBuffer.
  	console.log(info.data);
});

/* Turn the JSON strings into an array buffer. Chrome sockets require the data to be in this format to send */

function string2ArrayBuffer(string, callback) {
    var blob = new Blob([string]);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result);
    }
    f.readAsArrayBuffer(blob);
}

function arrayBuffer2String(buf, callback) {
    var blob = new Blob([buf]);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result)
    }
    f.readAsText(blob);
}<|endoftext|>


<commit_before>const RaspiCam = require("raspicam");
const moment = require('moment');
const _ = require('lodash');

var camera;

const defaultOptions = {
    mode: "photo",
    output: "./shots/this-will-be-overwritten-with-current-date.jpg",
    encoding: "jpg",
    width: 640,
    height: 480,
    quality: 50,
    timeout: 10000,
    timelapse: 200,
    thumb: "none",

    // image settings
    contrast: 20,
    brightness: 65,
    exposure: 'auto',

    // custom events
    onStart: null,
    onRead: null,
    onExit: null
}

function run(opts) {
    opts = opts || {};
    opts = Object.assign(defaultOptions, opts);

    const folderName = moment().format('YYMMDD');
    const fileName = moment().format('HHmmss');
    opts.output = `./shots/${folderName}/${fileName}_%04d.jpg`;

    if(camera){
        console.log('Capturing already in progress...');
        return;
    }

    camera = new RaspiCam(raspicamOptions(opts));

    camera.on("start", function( err, timestamp ){
        console.log("Capture photo started at " + timestamp );
        opts.onStart && opts.onStart(err, timestamp);
    });

    camera.on("read", function( err, timestamp, filename ){
        console.log("Capture photo image captured with filename: " + filename );
        opts.onRead && opts.onRead(err, timestamp, filename);
    });

    camera.on("exit", function( timestamp ){
        console.log("Capture photo child process has exited at " + timestamp );
        opts.onExit && opts.onExit(timestamp);
        camera = null;
    });

    camera.start();
    console.log('Capture initting done...');
}

/**
 * Pick options except nulls
 */
function raspicamOptions(opts){
    opts = opts || {};
    const excludeParams = [
        'onStart',
        'onRead',
        'onExit'
    ];
    return _.pickBy(opts, (val,key) => excludeParams.indexOf(key)<0);
}

module.exports = {
    run: run,
    camera: camera
}
<commit_msg>Remove preview when capturing<commit_after>const RaspiCam = require("raspicam");
const moment = require('moment');
const _ = require('lodash');

var camera;

const defaultOptions = {
    mode: "photo",
    output: "./shots/this-will-be-overwritten-with-current-date.jpg",
    encoding: "jpg",
    width: 640,
    height: 480,
    quality: 50,
    timeout: 10000,
    timelapse: 200,
    thumb: "none",
    nopreview: true,

    // image settings
    contrast: 20,
    brightness: 65,
    exposure: 'auto',

    // custom events
    onStart: null,
    onRead: null,
    onExit: null
}

function run(opts) {
    opts = opts || {};
    opts = Object.assign(defaultOptions, opts);

    const folderName = moment().format('YYMMDD');
    const fileName = moment().format('HHmmss');
    opts.output = `./shots/${folderName}/${fileName}_%04d.jpg`;

    if(camera){
        console.log('Capturing already in progress...');
        return;
    }

    camera = new RaspiCam(raspicamOptions(opts));

    camera.on("start", function( err, timestamp ){
        console.log("Capture photo started at " + timestamp );
        opts.onStart && opts.onStart(err, timestamp);
    });

    camera.on("read", function( err, timestamp, filename ){
        console.log("Capture photo image captured with filename: " + filename );
        opts.onRead && opts.onRead(err, timestamp, filename);
    });

    camera.on("exit", function( timestamp ){
        console.log("Capture photo child process has exited at " + timestamp );
        opts.onExit && opts.onExit(timestamp);
        camera = null;
    });

    camera.start();
    console.log('Capture initting done...');
}

/**
 * Pick options except nulls
 */
function raspicamOptions(opts){
    opts = opts || {};
    const excludeParams = [
        'onStart',
        'onRead',
        'onExit'
    ];
    return _.pickBy(opts, (val,key) => excludeParams.indexOf(key)<0);
}

module.exports = {
    run: run,
    camera: camera
}
<|endoftext|>


<commit_before>/* Copyright (c) 2013-present The TagSpaces Authors.
 * Use of this source code is governed by the MIT license which can be found in the LICENSE.txt file. */
/* globals marked, Mousetrap, CodeMirror */
'use strict';
sendMessageToHost({command: 'loadDefaultTextContent'});

var isCordova;
var isWin;
var isWeb;

$(document).ready(function() {
  function getParameterByName(name) {
    name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
      results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
  }

  var locale = getParameterByName('locale');
  var extSettings;
  loadExtSettings();

  isCordova = parent.isCordova;
  isWin = parent.isWin;
  // isWeb = parent.isWeb;

  // Init internationalization
  i18next.init({
    ns: {namespaces: ['ns.editorText']} ,
    debug: true ,
    lng: locale ,
    fallbackLng: 'en_US'
  } , function() {
    jqueryI18next.init(i18next, $);
    $('[data-i18n]').localize();
  });

  if (marked) {
    marked.setOptions({
      renderer: new marked.Renderer(),
      gfm: true,
      tables: true,
      breaks: true,
      pedantic: false,
      smartLists: true,
      smartypants: false
    });
  }

  // Init Markdown Preview functionality
  $('#markdownPreviewModal').on('show.bs.modal', function() {
    if (marked) {
      var modalBody = $('#markdownPreviewModal .modal-body');
      modalBody.html(marked(cmEditor.getValue(), {sanitize: true}));
    } else {
      console.log('markdown to html transformer not found');
    }
  });

  $('#markdownPreview').on('click', function(e) {
    $('#markdownPreviewModal').modal({show: true});
  });

  $('#mdHelpButton').on('click', function(e) {
    $('#markdownHelpModal').modal({show: true});
  });

  function handleLinks($element) {
    $element.find('a[href]').each(function() {
      var currentSrc = $(this).attr('href');
      $(this).bind('click', function(e) {
        e.preventDefault();
        sendMessageToHost({command: 'openLinkExternally', link: currentSrc});
      });
    });
  }

  function loadExtSettings() {
    extSettings = JSON.parse(localStorage.getItem('editorTextSettings'));
  }

  var filePath;

  function saveEditorText() {
    sendMessageToHost({command: 'saveDocument', filepath: filePath});
  }

});

var editorText;
var cmEditor;
var viewMode = true;

function viewerMode(isViewerMode) {
  console.log('viewerMode', isViewerMode);
  viewMode = isViewerMode;

  if (!viewMode) {
    cmEditor.focus();
  }

  //cmEditor.options.lineNumbers = isViewerMode;
  cmEditor.options.cursorBlinkRate = isViewerMode ? -1 : 530;
  cmEditor.options.readOnly = isViewerMode;
  cmEditor.options.foldGutter = isViewerMode;
  cmEditor.options.styleActiveLine = isViewerMode;
  cmEditor.options.matchBrackets = isViewerMode;
  cmEditor.options.showCursorWhenSelecting = isViewerMode;
  cmEditor.options.autofocus = !isViewerMode;
  cmEditor.refresh();
}

function setContent(content, filePath, isViewMode) {
  console.log('setContent EDITOR VIEWER: ', content, filePath, isViewMode);
  viewerMode(isViewMode);
  var $editorText = $('#editorText');
  $editorText.append("
");

  var filetype = [];
  filetype.h = 'clike';
  filetype.c = 'clike';
  filetype.clj = 'clojure';
  filetype.coffee = 'coffeescript';
  filetype.cpp = 'clike';
  filetype.cs = 'clike';
  filetype.css = 'css';
  filetype.groovy = 'groovy';
  filetype.haxe = 'haxe';
  filetype.htm = 'xml';
  filetype.html = 'xml';
  filetype.java = 'clike';
  filetype.js = 'javascript';
  filetype.ts = 'javascript';
  filetype.jsm = 'javascript';
  filetype.json = 'javascript';
  filetype.less = 'less';
  filetype.lua = 'lua';
  filetype.markdown = 'markdown';
  filetype.md = 'markdown';
  filetype.mdown = 'markdown';
  filetype.mdwn = 'markdown';
  filetype.mkd = 'markdown';
  filetype.ml = 'ocaml';
  filetype.mli = 'ocaml';
  filetype.pl = 'perl';
  filetype.php = 'php';
  filetype.py = 'python';
  filetype.rb = 'ruby';
  filetype.sh = 'shell';
  filetype.sql = 'sql';
  filetype.svg = 'xml';
  filetype.xml = 'xml';
  filetype.txt = 'txt';

  var fileExt = filePath.substring(filePath.lastIndexOf('.') + 1, filePath.length).toLowerCase();

  var mode = filetype[fileExt];

  var extensionDirectory;
  var modePath;
  if (mode) {
    modePath = extensionDirectory + '/libs/codemirror/mode/' + mode + '/' + mode;
  }

  if (mode !== filetype.markdown || mode !== filetype.md ||
    mode !== filetype.mdown || mode !== filetype.mdwn) {
    $('#markdownPreview').hide();
    $('#mdHelpButton').hide();
  } else {
    $('#markdownPreview').show();
    $('#mdHelpButton').show();
  }

  var place = document.getElementById('code');
  cmEditor = new CodeMirror(place, {
    mode: mode,
    lineNumbers: true,
    foldGutter: true,
    gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
    lineWrapping: true,
    tabSize: 2,
    //lineSeparator: isWin ? '\n\r' : null, // TODO check under windows if content contains \n\r -> set
    styleSelectedText: true,
    showCursorWhenSelecting: true,
    autofocus: !viewMode
    //theme: 'lesser-dark',
    //extraKeys: keys // workarrounded with bindGlobal plugin for mousetrap
  });

  CodeMirror.modeURL = 'libs/codemirror/mode/%N/%N.js';
  if (mode) {
    cmEditor.setOption('mode', mode);
    CodeMirror.autoLoadMode(cmEditor, mode);
  } else {
    throw new TypeError('Invalid mode !');
  }

  CodeMirror.on(cmEditor, 'change', function() {
    if (!viewMode) {
      sendMessageToHost({command: 'contentChangedInEditor' , filepath: filePath});
      $('.CodeMirror-cursor').show();
    } else {
      $('.CodeMirror-cursor').hide();
    }
  });

  cmEditor.setSize('100%', '100%');

  var UTF8_BOM = '\ufeff';
  if (content.indexOf(UTF8_BOM) === 0) {
    content = content.substring(1, content.length);
  }

  cmEditor.setValue(content);
  cmEditor.clearHistory();
  cmEditor.refresh();
}
<commit_msg>ext migration<commit_after>/* Copyright (c) 2013-present The TagSpaces Authors.
 * Use of this source code is governed by the MIT license which can be found in the LICENSE.txt file. */
/* globals marked, Mousetrap, CodeMirror */
'use strict';
sendMessageToHost({command: 'loadDefaultTextContent'});

var isCordova;
var isWin;
var isWeb;

$(document).ready(function() {
  function getParameterByName(name) {
    name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
      results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
  }

  var locale = getParameterByName('locale');
  var extSettings;
  loadExtSettings();

  isCordova = parent.isCordova;
  isWin = parent.isWin;
  // isWeb = parent.isWeb;

  // Init internationalization
  i18next.init({
    ns: {namespaces: ['ns.editorText']} ,
    debug: true ,
    lng: locale ,
    fallbackLng: 'en_US'
  } , function() {
    jqueryI18next.init(i18next, $);
    $('[data-i18n]').localize();
  });

  if (marked) {
    marked.setOptions({
      renderer: new marked.Renderer(),
      gfm: true,
      tables: true,
      breaks: true,
      pedantic: false,
      smartLists: true,
      smartypants: false
    });
  }

  // Init Markdown Preview functionality
  $('#markdownPreviewModal').on('show.bs.modal', function() {
    if (marked) {
      var modalBody = $('#markdownPreviewModal .modal-body');
      modalBody.html(marked(cmEditor.getValue(), {sanitize: true}));
    } else {
      console.log('markdown to html transformer not found');
    }
  });

  $('#markdownPreview').on('click', function(e) {
    $('#markdownPreviewModal').modal({show: true});
  });

  $('#mdHelpButton').on('click', function(e) {
    $('#markdownHelpModal').modal({show: true});
  });

  function handleLinks($element) {
    $element.find('a[href]').each(function() {
      var currentSrc = $(this).attr('href');
      $(this).bind('click', function(e) {
        e.preventDefault();
        sendMessageToHost({command: 'openLinkExternally', link: currentSrc});
      });
    });
  }

  function loadExtSettings() {
    extSettings = JSON.parse(localStorage.getItem('editorTextSettings'));
  }

  var filePath;

  function saveEditorText() {
    sendMessageToHost({command: 'saveDocument', filepath: filePath});
  }

});

var editorText;
var cmEditor;
var viewMode = true;

function viewerMode(isViewerMode) {
  viewMode = isViewerMode;
  if (!viewMode) {
    cmEditor.focus();
  }

  //cmEditor.options.lineNumbers = isViewerMode;
  cmEditor.options.cursorBlinkRate = isViewerMode ? -1 : 530;
  cmEditor.options.readOnly = isViewerMode;
  cmEditor.options.foldGutter = isViewerMode;
  cmEditor.options.styleActiveLine = isViewerMode;
  cmEditor.options.matchBrackets = isViewerMode;
  cmEditor.options.showCursorWhenSelecting = isViewerMode;
  cmEditor.options.autofocus = !isViewerMode;
  cmEditor.refresh();
}

function setContent(content, filePath, isViewMode) {
  var $editorText = $('#editorText');
  $editorText.append("
");

  var filetype = [];
  filetype.h = 'clike';
  filetype.c = 'clike';
  filetype.clj = 'clojure';
  filetype.coffee = 'coffeescript';
  filetype.cpp = 'clike';
  filetype.cs = 'clike';
  filetype.css = 'css';
  filetype.groovy = 'groovy';
  filetype.haxe = 'haxe';
  filetype.htm = 'xml';
  filetype.html = 'xml';
  filetype.java = 'clike';
  filetype.js = 'javascript';
  filetype.ts = 'javascript';
  filetype.jsm = 'javascript';
  filetype.json = 'javascript';
  filetype.less = 'less';
  filetype.lua = 'lua';
  filetype.markdown = 'markdown';
  filetype.md = 'markdown';
  filetype.mdown = 'markdown';
  filetype.mdwn = 'markdown';
  filetype.mkd = 'markdown';
  filetype.ml = 'ocaml';
  filetype.mli = 'ocaml';
  filetype.pl = 'perl';
  filetype.php = 'php';
  filetype.py = 'python';
  filetype.rb = 'ruby';
  filetype.sh = 'shell';
  filetype.sql = 'sql';
  filetype.svg = 'xml';
  filetype.xml = 'xml';
  filetype.txt = 'txt';

  var fileExt = filePath.substring(filePath.lastIndexOf('.') + 1, filePath.length).toLowerCase();

  var mode = filetype[fileExt];
  var extensionDirectory;
  var modePath;
  if (mode) {
    modePath = extensionDirectory + '/libs/codemirror/mode/' + mode + '/' + mode;
  }

  if (mode !== filetype.markdown || mode !== filetype.md ||
    mode !== filetype.mdown || mode !== filetype.mdwn) {
    $('#markdownPreview').hide();
    $('#mdHelpButton').hide();
  } else {
    $('#markdownPreview').show();
    $('#mdHelpButton').show();
  }

  var place = document.getElementById('code');
  cmEditor = new CodeMirror(place, {
    mode: mode,
    lineNumbers: true,
    foldGutter: true,
    gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
    lineWrapping: true,
    tabSize: 2,
    //lineSeparator: isWin ? '\n\r' : null, // TODO check under windows if content contains \n\r -> set
    styleSelectedText: true,
    showCursorWhenSelecting: true,
    autofocus: !viewMode
    //theme: 'lesser-dark',
    //extraKeys: keys // workarrounded with bindGlobal plugin for mousetrap
  });

  CodeMirror.modeURL = 'libs/codemirror/mode/%N/%N.js';
  if (mode) {
    cmEditor.setOption('mode', mode);
    CodeMirror.autoLoadMode(cmEditor, mode);
  } else {
    throw new TypeError('Invalid mode !');
  }

  viewerMode(isViewMode);

  CodeMirror.on(cmEditor, 'change', function() {
    if (!viewMode) {
      sendMessageToHost({command: 'contentChangedInEditor' , filepath: filePath});
      $('.CodeMirror-cursor').show();
    } else {
      $('.CodeMirror-cursor').hide();
    }
  });

  cmEditor.setSize('100%', '100%');

  var UTF8_BOM = '\ufeff';
  if (content.indexOf(UTF8_BOM) === 0) {
    content = content.substring(1, content.length);
  }

  cmEditor.setValue(content);
  cmEditor.clearHistory();
  cmEditor.refresh();
}
<|endoftext|>