<commit_before>/* global Platform */

(function () {

  var currentScript = document._currentScript || document.currentScript;

  var BrickAppbarElementPrototype = Object.create(HTMLElement.prototype);

  // Lifecycle methods
  BrickAppbarElementPrototype.attachedCallback = function () {

    var importDoc = currentScript.ownerDocument;
    var template = importDoc.querySelector('template');

    // fix styling for polyfill
    if (Platform.ShadowCSS) {
      var styles = template.content.querySelectorAll('style');
      for (var i = 0; i < styles.length; i++) {
        var style = styles[i];
        var cssText = Platform.ShadowCSS.shimStyle(style, 'brick-appbar');
        Platform.ShadowCSS.addCssToDocument(cssText);
        style.remove();
      }
    }

    // create shadowRoot and append template to it.
    var shadowRoot = this.createShadowRoot();
    shadowRoot.appendChild(template.content.cloneNode(true));
  };

  window.BrickAppbarElement = document.registerElement('brick-appbar', {
    prototype: BrickAppbarElementPrototype
  });

})();
<commit_msg>template id in the js as well<commit_after>/* global Platform */

(function () {

  var currentScript = document._currentScript || document.currentScript;

  var BrickAppbarElementPrototype = Object.create(HTMLElement.prototype);

  // Lifecycle methods
  BrickAppbarElementPrototype.attachedCallback = function () {

    var importDoc = currentScript.ownerDocument;
    var template = importDoc.querySelector('#brick-appbar-template');

    // fix styling for polyfill
    if (Platform.ShadowCSS) {
      var styles = template.content.querySelectorAll('style');
      for (var i = 0; i < styles.length; i++) {
        var style = styles[i];
        var cssText = Platform.ShadowCSS.shimStyle(style, 'brick-appbar');
        Platform.ShadowCSS.addCssToDocument(cssText);
        style.remove();
      }
    }

    // create shadowRoot and append template to it.
    var shadowRoot = this.createShadowRoot();
    shadowRoot.appendChild(template.content.cloneNode(true));
  };

  window.BrickAppbarElement = document.registerElement('brick-appbar', {
    prototype: BrickAppbarElementPrototype
  });

})();
<|endoftext|>


<commit_before>glob = require('glob');
var path = require('path');
var _ = require('lodash');

module.exports = function(app, appConfig, customDebug) {

  var debug = customDebug || function(){};

  var seedNodules = [], routes = {};

  var config = {
    // NOTE: the three route config params below must be specified in the nodule init method, they cannot be mutated at request-time
    // REQUIRED, must be unique within express app, can be String or RegExp or an array of either to handle multiple routes
    route: null,

    // get/post/put/delete
    routeVerb: 'get',

    // use to load routes before or after main group (use negative #s for to load route first - like z-index)
    routeIndex: 0,

    debugToConsole: false
  };

  var defaultConfig = _.extend(_.cloneDeep(config), appConfig);

  // TODO - look for a cleaner way to do this inside the nodules
  //        change name from module to nodule in all files
  app.initModule = initModule;

  return {
    seedNodules: seedNodules,
    loadNodules: loadNodules,
    registerRoutes: registerRoutes
  };

  function loadNodules(dir, exclude) {
    var root = dir || process.cwd(); // TOOD - should this be process.cwd() + '/app' ?
    glob.sync('./**/*.js', { cwd: root })
      .filter(doesntMatch.apply(this, exclude))
      .forEach(function(nodule) { require(path.join(root, nodule))(app); });
  }

  function initModule(file, config) {
    var seedNodule = _.extend(_.cloneDeep(defaultConfig), config); // merge config properties onto default config
    seedNodule.path = path.dirname(file);
    seedNodule.name = path.basename(file, '.js');

    // nodules can have multiple routes
    var routeArray = (typeof seedNodule.route === 'string') || (seedNodule.route instanceof RegExp) ? [seedNodule.route] : seedNodule.route;
    _.each(routeArray, function(routePath) {
      seedNodules[routePath] = seedNodule; // routes must me unique

      if (!routes[seedNodule.routeIndex])
        routes[seedNodule.routeIndex] = [];
      routes[seedNodule.routeIndex].push({path:routePath, verb:seedNodule.routeVerb});
    });
  }

  // register routes in order based on nodule.routeIndex (default 0, can be negative)
  function registerRoutes(middlewares) {
    var sortedRouteKeys = _.sortBy(_.keys(routes), function(num){ return 1*num; });
    _.each(sortedRouteKeys, function(key) {
      _.each(routes[key], function(route) {

        debug('registering route: ' + route.verb + ' ' + route.path);
        if (defaultConfig.debugToConsole) console.log('registering route: ' + route.verb + ' ' + route.path);

        app[route.verb].apply(app, [route.path].concat(middlewares));
      });
    });
  }
};

function doesntMatch() {
  var matchers = Array.prototype.slice.call(arguments, 0);
  return function(str) {
    var matches = !matchers.some(function(matcher) {
      return str.indexOf(matcher) !== -1;
    });
    return matches;
  };
}

<commit_msg>Fix global glob<commit_after>var glob = require('glob');
var path = require('path');
var _ = require('lodash');

module.exports = function(app, appConfig, customDebug) {

  var debug = customDebug || function(){};

  var seedNodules = [], routes = {};

  var config = {
    // NOTE: the three route config params below must be specified in the nodule init method, they cannot be mutated at request-time
    // REQUIRED, must be unique within express app, can be String or RegExp or an array of either to handle multiple routes
    route: null,

    // get/post/put/delete
    routeVerb: 'get',

    // use to load routes before or after main group (use negative #s for to load route first - like z-index)
    routeIndex: 0,

    debugToConsole: false
  };

  var defaultConfig = _.extend(_.cloneDeep(config), appConfig);

  // TODO - look for a cleaner way to do this inside the nodules
  //        change name from module to nodule in all files
  app.initModule = initModule;

  return {
    seedNodules: seedNodules,
    loadNodules: loadNodules,
    registerRoutes: registerRoutes
  };

  function loadNodules(dir, exclude) {
    var root = dir || process.cwd(); // TOOD - should this be process.cwd() + '/app' ?
    glob.sync('./**/*.js', { cwd: root })
      .filter(doesntMatch.apply(this, exclude))
      .forEach(function(nodule) { require(path.join(root, nodule))(app); });
  }

  function initModule(file, config) {
    var seedNodule = _.extend(_.cloneDeep(defaultConfig), config); // merge config properties onto default config
    seedNodule.path = path.dirname(file);
    seedNodule.name = path.basename(file, '.js');

    // nodules can have multiple routes
    var routeArray = (typeof seedNodule.route === 'string') || (seedNodule.route instanceof RegExp) ? [seedNodule.route] : seedNodule.route;
    _.each(routeArray, function(routePath) {
      seedNodules[routePath] = seedNodule; // routes must me unique

      if (!routes[seedNodule.routeIndex])
        routes[seedNodule.routeIndex] = [];
      routes[seedNodule.routeIndex].push({path:routePath, verb:seedNodule.routeVerb});
    });
  }

  // register routes in order based on nodule.routeIndex (default 0, can be negative)
  function registerRoutes(middlewares) {
    var sortedRouteKeys = _.sortBy(_.keys(routes), function(num){ return 1*num; });
    _.each(sortedRouteKeys, function(key) {
      _.each(routes[key], function(route) {

        debug('registering route: ' + route.verb + ' ' + route.path);
        if (defaultConfig.debugToConsole) console.log('registering route: ' + route.verb + ' ' + route.path);

        app[route.verb].apply(app, [route.path].concat(middlewares));
      });
    });
  }
};

function doesntMatch() {
  var matchers = Array.prototype.slice.call(arguments, 0);
  return function(str) {
    var matches = !matchers.some(function(matcher) {
      return str.indexOf(matcher) !== -1;
    });
    return matches;
  };
}

<|endoftext|>


<commit_before>var vm = require('vm');
var fs = require('fs');
var createExpect = require('./createExpect');
var locateBabelrc = require('./locateBabelrc');

var transpile;
var hasBabel = false;
try {
  var babelCore = require.main.require('babel-core');
  var babelrc = locateBabelrc();
  var babelOptions = JSON.parse(fs.readFileSync(babelrc, 'utf-8'));
  hasBabel = true;

  transpile = function transpile(code) {
    var babelResult = babelCore.transform(code, {
      ...babelOptions,
      sourceMaps: false,
      compact: false
    });

    return babelResult.code.replace(/'use strict';/, '');
  };
} catch (e) {
  transpile = function transpile(code) {
    return code;
  };
}

function isPromise(value) {
  return (
    value &&
    typeof value.then === 'function' &&
    typeof value.caught === 'function'
  );
}

function getErrorMessage(expect, format, error) {
  if (error) {
    if (error.getErrorMessage) {
      var output = expect.createOutput
        ? expect.createOutput(format)
        : expect.output.clone(format);
      return error.getErrorMessage({ output: output }).toString(format);
    } else if (error.output) {
      return error.output.toString(format);
    } else {
      return expect.output
        .clone(format)
        .error((error && error.message) || '')
        .toString(format);
    }
  } else {
    return '';
  }
}

module.exports = async function(snippets, options) {
  var oldGlobal = Object.assign({}, global);
  var expect = createExpect(options);
  global.expect = expect.clone();
  global.require = require;

  if (hasBabel) {
    var preambleSeparator =
      '\n//---------------------preamble----------------------\n';
    var separator = '\n//---------------------separator---------------------\n';

    var exampleSnippets = snippets.filter(function(snippet) {
      return snippet.lang === 'javascript' && snippet.flags.evaluate;
    });

    if (exampleSnippets.length) {
      var codeForTranspilation =
        preambleSeparator +
        exampleSnippets
          .map(function(snippet) {
            return snippet.flags.async
              ? `(function () {${snippet.code}})();`
              : snippet.code;
          })
          .join(separator);

      var transpiledCode = transpile(codeForTranspilation);
      var transpiledSnippets = transpiledCode.split(
        new RegExp(`${preambleSeparator}|${separator}`)
      );

      var preamble = transpiledSnippets[0];
      vm.runInThisContext(preamble);

      transpiledSnippets.slice(1).forEach(function(transpiledSnippet, i) {
        exampleSnippets[i].code = transpiledSnippet;
      });
    }
  }

  for (const snippet of snippets) {
    if (snippet.lang === 'javascript' && snippet.flags.evaluate) {
      try {
        if (snippet.flags.freshExpect) {
          global.expect = expect.clone();
        }

        if (snippet.flags.async) {
          var promise = vm.runInThisContext(
            hasBabel ? snippet.code : `(function () {${snippet.code}})();`
          );
          if (!isPromise(promise)) {
            throw new Error(
              `Async code block did not return a promise or throw\n${snippet.code}`
            );
          }

          try {
            await promise;
          } catch (e) {
            snippet.htmlErrorMessage = getErrorMessage(
              global.expect,
              'html',
              e
            );
            snippet.errorMessage = getErrorMessage(global.expect, 'text', e);
          }
        } else {
          vm.runInThisContext(snippet.code);
        }
      } catch (e) {
        snippet.htmlErrorMessage = getErrorMessage(global.expect, 'html', e);
        snippet.errorMessage = getErrorMessage(global.expect, 'text', e);
      }
    }
  }

  Object.keys(global).forEach(function(key) {
    if (!(key in oldGlobal)) {
      delete global[key];
    }
  });

  Object.assign(global, oldGlobal);
};
<commit_msg>Roll back the use of Object.assign() in evaluateSnippets.<commit_after>var vm = require('vm');
var fs = require('fs');
var createExpect = require('./createExpect');
var locateBabelrc = require('./locateBabelrc');

var transpile;
var hasBabel = false;
try {
  var babelCore = require.main.require('babel-core');
  var babelrc = locateBabelrc();
  var babelOptions = JSON.parse(fs.readFileSync(babelrc, 'utf-8'));
  hasBabel = true;

  transpile = function transpile(code) {
    var babelResult = babelCore.transform(code, {
      ...babelOptions,
      sourceMaps: false,
      compact: false
    });

    return babelResult.code.replace(/'use strict';/, '');
  };
} catch (e) {
  transpile = function transpile(code) {
    return code;
  };
}

function extend(target) {
  for (var i = 1; i < arguments.length; i += 1) {
    var source = arguments[i];
    Object.keys(source).forEach(function(key) {
      target[key] = source[key];
    });
  }
  return target;
}

function isPromise(value) {
  return (
    value &&
    typeof value.then === 'function' &&
    typeof value.caught === 'function'
  );
}

function getErrorMessage(expect, format, error) {
  if (error) {
    if (error.getErrorMessage) {
      var output = expect.createOutput
        ? expect.createOutput(format)
        : expect.output.clone(format);
      return error.getErrorMessage({ output: output }).toString(format);
    } else if (error.output) {
      return error.output.toString(format);
    } else {
      return expect.output
        .clone(format)
        .error((error && error.message) || '')
        .toString(format);
    }
  } else {
    return '';
  }
}

module.exports = async function(snippets, options) {
  var oldGlobal = extend({}, global);
  var expect = createExpect(options);
  global.expect = expect.clone();
  global.require = require;

  if (hasBabel) {
    var preambleSeparator =
      '\n//---------------------preamble----------------------\n';
    var separator = '\n//---------------------separator---------------------\n';

    var exampleSnippets = snippets.filter(function(snippet) {
      return snippet.lang === 'javascript' && snippet.flags.evaluate;
    });

    if (exampleSnippets.length) {
      var codeForTranspilation =
        preambleSeparator +
        exampleSnippets
          .map(function(snippet) {
            return snippet.flags.async
              ? `(function () {${snippet.code}})();`
              : snippet.code;
          })
          .join(separator);

      var transpiledCode = transpile(codeForTranspilation);
      var transpiledSnippets = transpiledCode.split(
        new RegExp(`${preambleSeparator}|${separator}`)
      );

      var preamble = transpiledSnippets[0];
      vm.runInThisContext(preamble);

      transpiledSnippets.slice(1).forEach(function(transpiledSnippet, i) {
        exampleSnippets[i].code = transpiledSnippet;
      });
    }
  }

  for (const snippet of snippets) {
    if (snippet.lang === 'javascript' && snippet.flags.evaluate) {
      try {
        if (snippet.flags.freshExpect) {
          global.expect = expect.clone();
        }

        if (snippet.flags.async) {
          var promise = vm.runInThisContext(
            hasBabel ? snippet.code : `(function () {${snippet.code}})();`
          );
          if (!isPromise(promise)) {
            throw new Error(
              `Async code block did not return a promise or throw\n${snippet.code}`
            );
          }

          try {
            await promise;
          } catch (e) {
            snippet.htmlErrorMessage = getErrorMessage(
              global.expect,
              'html',
              e
            );
            snippet.errorMessage = getErrorMessage(global.expect, 'text', e);
          }
        } else {
          vm.runInThisContext(snippet.code);
        }
      } catch (e) {
        snippet.htmlErrorMessage = getErrorMessage(global.expect, 'html', e);
        snippet.errorMessage = getErrorMessage(global.expect, 'text', e);
      }
    }
  }

  Object.keys(global).forEach(function(key) {
    if (!(key in oldGlobal)) {
      delete global[key];
    }
  });

  // local function used for compatibility with node 8
  extend(global, oldGlobal);
};
<|endoftext|>


<commit_before>//set main entry point path
global.BOT_DIR = require('path').resolve(__dirname, '..');
global.LIBS_DIR = require('path').resolve(BOT_DIR, 'libs');
global.MODULES_DIR = require('path').resolve(BOT_DIR, 'modules');

var logger = require(LIBS_DIR + '/logger');

function Bot() {
	//events
	var dispatcher = new(require('events').EventEmitter)();
	dispatcher.setMaxListeners(0); //remove listener limit
	//add empty config
	var config = new(require(LIBS_DIR + '/config').Config)();
	//add MM
	var moduleManager = new(require(LIBS_DIR + '/moduleManager').ModuleManager)(dispatcher, config);

	//load module on new listener
	dispatcher.on('newListener', function(event, listener) {
		var i, name;
		if(((i = event.indexOf('/')) + 1) && (name = event.substr(0, i))) {
			if(moduleManager.exists(name)) {
				moduleManager.load(name);
			}
		}
	});

	//bot config
	this.config = config;
	//bot MM
	this.modules = moduleManager;
	//dispatcher
	this.dispatcher = dispatcher;

	//list of core modules
	this.core_modules = {
		'irc': true
	};

	//bind to exit event of main process
	var bot = this;
	process.on('exit', function() {
		bot.exit();
	});

	//shutdown on ctrl+c gracefully
	process.on('SIGINT', function() {
		bot.exit(0);
	});

	// This will override SIGTSTP and prevent the program from going to the background.
	process.on('SIGTSTP', function() {});
}

Bot.prototype.exit = function(code) {
	this.emit('halt', this);
	this.unloadModules();
	if(code) process.exit(code);
};

Bot.prototype.addListener = function() {
	this.dispatcher.addListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.on = function() {
	this.dispatcher.on.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.off = Bot.prototype.removeListener = function() {
	this.dispatcher.removeListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.once = function() {
	this.dispatcher.once.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.emit = function() {
	this.dispatcher.emit.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.loadConfig = function loadConfig(config, callback) {
	var bot = this;

	var error = null;
	if(typeof config === 'function' && typeof callback === 'undefined') {
		callback = config;
		config = undefined;
	}

	if(typeof config === 'string') {
		try {
			bot.config.extend(require(BOT_DIR + '/' + config));
			logger.info('Config loaded!');
		} catch(e) {
			logger.error('Cannot load config!');
			error = new Error('Cannot load config!');
		}
	} else if(config instanceof Object) {
		bot.config.extend(config);
	} else {
		try {
			bot.config.extend(require(BOT_DIR + '/config.json'));
		} catch(e) {
			logger.error('Cannot load config!');
			error = new Error('Cannot load config!');
		}
	}

	//make sure we have important values
	if(typeof bot.config.bot === 'undefined') {
		bot.config.bot = {
			'name': 'IRC-PONY',
			'modules': 'modules.json'
		};
	} else {
		if(typeof bot.config.bot.name === 'undefined') {
			bot.config.bot.name = 'IRC-PONY';
		}
		if(typeof bot.config.bot.modules === 'undefined') {
			bot.config.bot.modules = 'modules.json';
		}
	}

	if(callback) callback(error, bot.config);
	else if(error) throw error;

	logger.info('Config loaded!');
	return bot;
};

Bot.prototype.loadModules = function loadModules(modules, callback) {
	var bot = this;

	if(typeof modules === 'function' && typeof callback === 'undefined') {
		callback = modules;
		modules = {};
	}

	if(typeof bot.config.bot === 'undefined') { //we need atleast empty bot config
		bot.config.bot = {
			'modules': 'modules.json'
		};
	}

	var error = null;
	if(typeof modules === 'string') {
		bot.config.bot.modules = modules;
		modules = {};
	} else if(typeof modules === 'object' && modules instanceof Array) {
		var tmp = modules.slice(0);
		modules = {};
		for(var i = 0; i < tmp.length; i++) {
			modules[tmp[i]] = true;
		}

	} else if(typeof modules !== 'object' && typeof bot.config.bot.modules === 'string') {
		modules = {};
	} else if(typeof modules !== 'object') {
		logger.error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');
		error = new Error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');

		modules = {};
	}

	//first load core modules
	Object.keys(bot.core_modules).forEach(function(name) {
		if(bot.core_modules[name] === true) {
			bot.modules.load(name);
		}
	});

	//then custom modules
	if(Object.keys(modules).length <= 0) {
		try {
			modules = require(BOT_DIR + '/' + bot.config.bot.modules);
		} catch(e) {
			modules = {};
			logger.error('Cannot load modules file \'' + bot.config.bot.modules + '\'!');
			error = new Error('Cannot load modules file \'' + bot.config.bot.modules + '\'!');
		}
	}

	var keys = Object.keys(modules);
	if(keys.length > 0) {
		keys.forEach(function(name) {
			if(modules[name] === true) {
				bot.modules.load(name);
			}
		});
	}

	if(callback) callback(error, bot.modules);
	else if(error) throw error;

	logger.info('Modules loaded!');
	return bot;
};

Bot.prototype.unloadModules = function() {
	var bot = this;
	bot.modules.getModules().forEach(function(m) {
		bot.modules.unload(m.name);
	});
	logger.info('Modules unloaded!');
};

Bot.prototype.load = function load(names, callback) {
	var bot = this;

	if(!(names instanceof Array)) {
		names = [names];
	}

	var recallback = callback ?
	function(err, module, mm) {
		callback(err, module, mm, bot);
	} : undefined;

	names.forEach(function(name) {
		bot.modules.load(name, recallback);
	});

	return bot;
};

Bot.prototype.unload = function unload(names, callback) {
	var bot = this;

	if(!(names instanceof Array)) {
		names = [names];
	}

	var recallback = callback ?
	function(err, mm) {
		callback(err, mm, bot);
	} : undefined;

	names.forEach(function(name) {
		bot.modules.unload(name, recallback);
	});

	return bot;
};

Bot.prototype.run = function run() {
	this.emit('init', this);
	return this;
};

Bot.prototype.end = function end() {
	//halt event is emitted on process 'exit'
	process.nextTick(function() {
		process.exit(0);
	});
};

module.exports.Bot = Bot;
module.exports.create = function() {
	return new Bot();
};<commit_msg>bot end more like<commit_after>//set main entry point path
global.BOT_DIR = require('path').resolve(__dirname, '..');
global.LIBS_DIR = require('path').resolve(BOT_DIR, 'libs');
global.MODULES_DIR = require('path').resolve(BOT_DIR, 'modules');

var logger = require(LIBS_DIR + '/logger');

function Bot() {
	//events
	var dispatcher = new(require('events').EventEmitter)();
	dispatcher.setMaxListeners(0); //remove listener limit
	//add empty config
	var config = new(require(LIBS_DIR + '/config').Config)();
	//add MM
	var moduleManager = new(require(LIBS_DIR + '/moduleManager').ModuleManager)(dispatcher, config);

	//load module on new listener
	dispatcher.on('newListener', function(event, listener) {
		var i, name;
		if(((i = event.indexOf('/')) + 1) && (name = event.substr(0, i))) {
			if(moduleManager.exists(name)) {
				moduleManager.load(name);
			}
		}
	});

	//bot config
	this.config = config;
	//bot MM
	this.modules = moduleManager;
	//dispatcher
	this.dispatcher = dispatcher;

	//list of core modules
	this.core_modules = {
		'irc': true
	};

	this.halting = false;
	//bind to exit event of main process
	var bot = this;
	process.on('exit', function() {
		if(!bot.halting) bot.emit('halt', bot);
		bot.unloadModules();
	});

	//shutdown on ctrl+c gracefully
	process.on('SIGINT', function() {
		bot.halting = true;
		bot.emit('halt', bot);
		process.exit(0);
	});

	// This will override SIGTSTP and prevent the program from going to the background.
	process.on('SIGTSTP', function() {});
}

Bot.prototype.addListener = function() {
	this.dispatcher.addListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.on = function() {
	this.dispatcher.on.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.off = Bot.prototype.removeListener = function() {
	this.dispatcher.removeListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.once = function() {
	this.dispatcher.once.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.emit = function() {
	this.dispatcher.emit.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.loadConfig = function loadConfig(config, callback) {
	var bot = this;

	var error = null;
	if(typeof config === 'function' && typeof callback === 'undefined') {
		callback = config;
		config = undefined;
	}

	if(typeof config === 'string') {
		try {
			bot.config.extend(require(BOT_DIR + '/' + config));
			logger.info('Config loaded!');
		} catch(e) {
			logger.error('Cannot load config!');
			error = new Error('Cannot load config!');
		}
	} else if(config instanceof Object) {
		bot.config.extend(config);
	} else {
		try {
			bot.config.extend(require(BOT_DIR + '/config.json'));
		} catch(e) {
			logger.error('Cannot load config!');
			error = new Error('Cannot load config!');
		}
	}

	//make sure we have important values
	if(typeof bot.config.bot === 'undefined') {
		bot.config.bot = {
			'name': 'IRC-PONY',
			'modules': 'modules.json'
		};
	} else {
		if(typeof bot.config.bot.name === 'undefined') {
			bot.config.bot.name = 'IRC-PONY';
		}
		if(typeof bot.config.bot.modules === 'undefined') {
			bot.config.bot.modules = 'modules.json';
		}
	}

	if(callback) callback(error, bot.config);
	else if(error) throw error;

	logger.info('Config loaded!');
	return bot;
};

Bot.prototype.loadModules = function loadModules(modules, callback) {
	var bot = this;

	if(typeof modules === 'function' && typeof callback === 'undefined') {
		callback = modules;
		modules = {};
	}

	if(typeof bot.config.bot === 'undefined') { //we need atleast empty bot config
		bot.config.bot = {
			'modules': 'modules.json'
		};
	}

	var error = null;
	if(typeof modules === 'string') {
		bot.config.bot.modules = modules;
		modules = {};
	} else if(typeof modules === 'object' && modules instanceof Array) {
		var tmp = modules.slice(0);
		modules = {};
		for(var i = 0; i < tmp.length; i++) {
			modules[tmp[i]] = true;
		}

	} else if(typeof modules !== 'object' && typeof bot.config.bot.modules === 'string') {
		modules = {};
	} else if(typeof modules !== 'object') {
		logger.error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');
		error = new Error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');

		modules = {};
	}

	//first load core modules
	Object.keys(bot.core_modules).forEach(function(name) {
		if(bot.core_modules[name] === true) {
			bot.modules.load(name);
		}
	});

	//then custom modules
	if(Object.keys(modules).length <= 0) {
		try {
			modules = require(BOT_DIR + '/' + bot.config.bot.modules);
		} catch(e) {
			modules = {};
			logger.error('Cannot load modules file \'' + bot.config.bot.modules + '\'!');
			error = new Error('Cannot load modules file \'' + bot.config.bot.modules + '\'!');
		}
	}

	var keys = Object.keys(modules);
	if(keys.length > 0) {
		keys.forEach(function(name) {
			if(modules[name] === true) {
				bot.modules.load(name);
			}
		});
	}

	if(callback) callback(error, bot.modules);
	else if(error) throw error;

	logger.info('Modules loaded!');
	return bot;
};

Bot.prototype.unloadModules = function() {
	var bot = this;
	bot.modules.getModules().forEach(function(m) {
		bot.modules.unload(m.name);
	});
	logger.info('Modules unloaded!');
};

Bot.prototype.load = function load(names, callback) {
	var bot = this;

	if(!(names instanceof Array)) {
		names = [names];
	}

	var recallback = callback ?
	function(err, module, mm) {
		callback(err, module, mm, bot);
	} : undefined;

	names.forEach(function(name) {
		bot.modules.load(name, recallback);
	});

	return bot;
};

Bot.prototype.unload = function unload(names, callback) {
	var bot = this;

	if(!(names instanceof Array)) {
		names = [names];
	}

	var recallback = callback ?
	function(err, mm) {
		callback(err, mm, bot);
	} : undefined;

	names.forEach(function(name) {
		bot.modules.unload(name, recallback);
	});

	return bot;
};

Bot.prototype.run = function run() {
	this.emit('init', this);
	return this;
};

Bot.prototype.end = function end() {
	//halt event is emitted on process 'exit'
	process.nextTick(function() {
		process.exit(0);
	});
};

module.exports.Bot = Bot;
module.exports.create = function() {
	return new Bot();
};<|endoftext|>


<commit_before>var GReYBot = require('../greybot');
var util = require('util');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();

exports.commands = [
	'define'
];

exports.define = {
	usage: '<word>',
	description: 'looks up a word in the Merriam-Webster Collegiate Dictionary',
	process: (msg, suffix) => {
    	var word = suffix;
		if (!word) {
			msg.channel.send('I won\'t define an empty string.');
			return;
		}
		var url = 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/' + word + '?key=' + GReYBot.Auth.dictionary_api_key;
		require('request')(url,
			function (err, res, body) {
				let definitionResult = "";
				parser.parseString(body, function (err, result) {
					let wordList = result.entry_list.entry;
					let phonetic = '';
					phonetic += wordList[0].pr.map(entry => {
						if (typeof entry === 'object') {
							return entry['_'];
						}
						return entry;
					}).join('\n');
					definitionResult += '*[' + phonetic + ']*\n';
					definitionResult += 'Hear it: http://media.merriam-webster.com/soundc11/' + wordList[0].sound[0].wav[0].slice(0,1) + '/' + wordList[0].sound[0].wav[0] + '\n\n';
					wordList.forEach(wordResult => {
						let defList = '';
						let defArray = wordResult.def[0].dt;
						if (wordResult.ew[0] !== word) { return; };
						definitionResult += '__' + wordResult.fl[0] + '__\n';
						defArray = defArray.filter(item => {
							if (typeof item === 'object') {
								item['_'] = item['_'].trim();
								return item['_'] !== ':';
							}
							item = item.trim();
							return item !== ':';
						});
						defList += defArray.map(entry => {
							if (typeof entry === 'object') {
								return entry['_'];
							}
							return entry;
						}).join('\n');
						definitionResult += defList + '\n\n';
					});

					msg.channel.send({
						embed: {
							color: GReYBot.Config.defaultEmbedColor,
							title: word,
							description: definitionResult
						}
					});
				});
			});
	}
}
<commit_msg>this isnt showing locally. fixing it online<commit_after>var GReYBot = require('../greybot');
var util = require('util');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();

exports.commands = [
	'define'
];

exports.define = {
	usage: '<word>',
	description: 'looks up a word in the Merriam-Webster Collegiate Dictionary',
	process: (msg, suffix) => {
    		var word = suffix;
		if (!word) {
			msg.channel.send('I won\'t define an empty string.');
			return;
		}
		var url = 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/' + word + '?key=' + GReYBot.Auth.dictionary_api_key;
		require('request')(url,
			function (err, res, body) {
				let definitionResult = "";
				parser.parseString(body, function (err, result) {
					let wordList = result.entry_list.entry;
					let phonetic = '';
					phonetic += wordList[0].pr.map(entry => {
						if (typeof entry === 'object') {
							return entry['_'];
						}
						return entry;
					}).join('\n');
					definitionResult += '*[' + phonetic + ']*\n';
					definitionResult += 'Hear it: http://media.merriam-webster.com/soundc11/' + wordList[0].sound[0].wav[0].slice(0,1) + '/' + wordList[0].sound[0].wav[0] + '\n\n';
					wordList.forEach(wordResult => {
						let defList = '';
						let defArray = wordResult.def[0].dt;
						if (wordResult.ew[0] !== word) { return; };
						definitionResult += '__' + wordResult.fl[0] + '__\n';
						defArray = defArray.filter(item => {
							if (typeof item === 'object') {
								item['_'] = item['_'].trim();
								return item['_'] !== ':';
							}
							item = item.trim();
							return item !== ':';
						});
						defList += defArray.map(entry => {
							if (typeof entry === 'object') {
								return entry['_'];
							}
							return entry;
						}).join('\n');
						definitionResult += defList + '\n\n';
					});

					msg.channel.send({
						embed: {
							color: GReYBot.Config.defaultEmbedColor,
							title: word,
							description: definitionResult
						}
					});
				});
			});
	}
}
<|endoftext|>


<commit_before>// Example: Record a sound and then play it back.
// We need p5.AudioIn (mic / sound source), p5.SoundRecorder
// (records the sound), and a p5.SoundFile (play back).

let mic, recorder, soundFile;

let state = 0; // mousePress will increment from state = 0 (Record), to 1(Stop), to 2(Play)
let isRecordingStarted = false;
let isResultPlayed = false;

function setup() {
  createCanvas(400, 400);
  background(200);
  fill(0);
  text('Enable mic and click the mouse to begin recording', 20, 20);

  // create an audio in
  mic = new p5.AudioIn();

  // create a sound recorder
  recorder = new p5.SoundRecorder();

  // connect the mic to the recorder
  recorder.setInput(mic);

  // create an empty sound file that we will use to playback the recording
  soundFile = new p5.SoundFile();
}

function mousePressed() {
  userStartAudio();
  // use the '.enabled' boolean to make sure user enabled the mic (otherwise we'd record silence)
  if (!isRecordingStarted && !isResultPlayed) {
    // users must manually enable their browser microphone for recording to work properly!
    mic.start(function () {
      // Tell recorder to record to a p5.SoundFile which we will use for playback
      recorder.record(soundFile);

      background(255, 0, 0);
      text('Recording now! Click to stop.', 20, 20);
      isRecordingStarted = true;
    });
  } else if (isRecordingStarted && !isResultPlayed) {
    recorder.stop(); // stop recorder, and send the result to soundFile
    mic.dispose();
    background(0, 255, 0);
    text('Recording stopped. Click to play', 20, 20);
    isResultPlayed = true;
  } else if (isRecordingStarted && isResultPlayed) {
    soundFile.play(); // play the result!
  }
}
<commit_msg>(Gsoc'21)💚 removed state variable initialization<commit_after>// Example: Record a sound and then play it back.
// We need p5.AudioIn (mic / sound source), p5.SoundRecorder
// (records the sound), and a p5.SoundFile (play back).

let mic, recorder, soundFile;

let isRecordingStarted = false;
let isResultPlayed = false;

function setup() {
  createCanvas(400, 400);
  background(200);
  fill(0);
  text('Enable mic and click the mouse to begin recording', 20, 20);

  // create an audio in
  mic = new p5.AudioIn();

  // create a sound recorder
  recorder = new p5.SoundRecorder();

  // connect the mic to the recorder
  recorder.setInput(mic);

  // create an empty sound file that we will use to playback the recording
  soundFile = new p5.SoundFile();
}

function mousePressed() {
  userStartAudio();
  // use the '.enabled' boolean to make sure user enabled the mic (otherwise we'd record silence)
  if (!isRecordingStarted && !isResultPlayed) {
    // users must manually enable their browser microphone for recording to work properly!
    mic.start(function () {
      // Tell recorder to record to a p5.SoundFile which we will use for playback
      recorder.record(soundFile);

      background(255, 0, 0);
      text('Recording now! Click to stop.', 20, 20);
      isRecordingStarted = true;
    });
  } else if (isRecordingStarted && !isResultPlayed) {
    recorder.stop(); // stop recorder, and send the result to soundFile
    mic.dispose();
    background(0, 255, 0);
    text('Recording stopped. Click to play', 20, 20);
    isResultPlayed = true;
  } else if (isRecordingStarted && isResultPlayed) {
    soundFile.play(); // play the result!
  }
}
<|endoftext|>


<commit_before>/*!
 * VIZABI POP BY AGE Component
 */

(function () {

  "use strict";

  var Vizabi = this.Vizabi;
  var utils = Vizabi.utils;

  //warn client if d3 is not defined
  if (!Vizabi._require('d3')) return;

  //POP BY AGE CHART COMPONENT
  Vizabi.Component.extend('gapminder-popbyage', {

    /**
     * Initializes the component (Bar Chart).
     * Executed once before any template is rendered.
     * @param {Object} config The options passed to the component
     * @param {Object} context The component's parent
     */
    init: function (config, context) {
      this.name = 'popbyage';
      this.template = 'src/tools/popbyage/popbyage.html';

      //define expected models for this component
      this.model_expects = [{
        name: "time",
        type: "time"
      }, {
        name: "entities",
        type: "entities"
      }, {
        name: "age",
        type: "entities"
      },{
        name: "marker",
        type: "model"
      }, {
        name: "language",
        type: "language"
      }];

      var _this = this;
      this.model_binds = {
        "change:time:value": function (evt) {
          _this._updateEntities();
        },
        "change:entities:show": function (evt) {
          console.log('Trying to change show');
        },
        "change:age:select": function (evt) {
          _this._selectBars();
        }
      };

      //contructor is the same as any component
      this._super(config, context);

      this.xScale = null;
      this.yScale = null;
      this.cScale = d3.scale.category10();

      this.xAxis = d3.svg.axisSmart();
      this.yAxis = d3.svg.axisSmart();
    },

    /**
     * DOM is ready
     */
    readyOnce: function () {

      this.element = d3.select(this.element);

      this.graph = this.element.select('.vzb-bc-graph');
      this.yAxisEl = this.graph.select('.vzb-bc-axis-y');
      this.xAxisEl = this.graph.select('.vzb-bc-axis-x');
      this.yTitleEl = this.graph.select('.vzb-bc-axis-y-title');
      this.bars = this.graph.select('.vzb-bc-bars');
      this.labels = this.graph.select('.vzb-bc-labels');

      this.title = this.element.select('.vzb-bc-title');
      this.year = this.element.select('.vzb-bc-year');

      //only allow selecting one at a time
      this.model.age.selectMultiple(false);

      var _this = this;
      this.on("resize", function () {
        _this._updateEntities();
      });
    },

    /*
     * Both model and DOM are ready
     */
    ready: function () {

      this.AGEDIM = this.model.age.getDimension();
      this.TIMEDIM = this.model.time.getDimension();

      this.timeFormatter = d3.time.format(this.model.time.formatOutput);

      this.updateUIStrings();
      this._updateIndicators();
      this.resize();
      this._updateEntities();
      this._updateEntities();
    },

    updateUIStrings: function(){
      this.translator = this.model.language.getTFunction();

      var titleStringY = this.translator("indicator/" + this.model.marker.axis_y.which);

      var yTitle = this.yTitleEl.selectAll("text").data([0]);
      yTitle.enter().append("text");
      yTitle
        .attr("y", "-6px")
        .attr("x", "-9px")
        .attr("dx", "-0.72em")
        .text(titleStringY);
    },

    /**
     * Changes labels for indicators
     */
    _updateIndicators: function () {
      var _this = this;
      this.duration = this.model.time.speed;

      this.yScale = this.model.marker.axis_y.getScale(false);
      this.xScale = this.model.marker.axis_x.getScale(false);
      this.cScale = this.model.marker.color.getScale();

      this.yAxis.tickFormat(_this.model.marker.axis_y.tickFormatter);
      this.xAxis.tickFormat(_this.model.marker.axis_x.tickFormatter);
    },

    /**
     * Updates entities
     */
    _updateEntities: function () {

      var _this = this;
      var time = this.model.time;
      var timeFormatter = d3.time.format(this.model.time.formatInput);
      var ageDim = this.AGEDIM;
      var timeDim = this.TIMEDIM;
      var duration = (time.playing) ? time.speed : 0;
      var filter = {};
      filter[timeDim] = time.value;
      var items = this.model.marker.getKeys(filter);
      var values = this.model.marker.getValues(filter, [ageDim]);

      //TODO: this should be done at a data layer
      //Year Grouping

      var test = function(d) {
        return parseInt(d, 10) % group_by === 1;
      }

      var group_by = this.model.marker.group_by;
      if(group_by > 1) {
        items = items.filter(function(d) {
          return test(d[ageDim]);
        });

        var new_values = {};
        utils.forEach(values, function(hook, hook_name) {
          new_values[hook_name] = {};
          var hook_values = new_values[hook_name];
          var curr = false;
          utils.forEach(hook, function(val, key) {
            if(test(key) || curr === false) {
              curr = key;
              hook_values[curr] = val;
            }
            //if it's a number and axis x
            if(!utils.isNaN(val) && hook_name === "axis_x") {
              hook_values[curr] = parseFloat(hook_values[curr]) + parseFloat(val);
            }
          });

        });

        values = new_values;

      }

      //End Year Grouping

      this.model.age.setVisible(items);

      this.entityBars = this.bars.selectAll('.vzb-bc-bar')
        .data(items);

      this.entityLabels = this.labels.selectAll('.vzb-bc-label')
        .data(items);

      //exit selection
      this.entityBars.exit().remove();
      this.entityLabels.exit().remove();

      var highlight = this._highlightBar.bind(this);
      var unhighlight = this._unhighlightBars.bind(this)

      //enter selection -- init bars
      this.entityBars.enter().append("g")
          .attr("class", "vzb-bc-bar")
          .attr("id", function(d) {
            return  "vzb-bc-bar-"+d[ageDim];
          })
          .on("mousemove", highlight)
          .on("mouseout", unhighlight)
          .on("click", function (d, i) {
            _this.model.age.selectEntity(d);
          })
          .append('rect');

      this.entityLabels.enter().append("g")
          .attr("class", "vzb-bc-label")
          .attr("id", function(d) {
            return  "vzb-bc-label-"+d[ageDim];
          })
          .on("mousemove", highlight)
          .on("mouseout", unhighlight)
          .append('text')
          .attr("class", "vzb-bc-age");

      var barWidth = this.height / items.length;

      this.bars.selectAll('.vzb-bc-bar > rect')
        .attr("fill", function (d) {
          return _this.cScale(values.color[d[ageDim]]);
        })
        .style("stroke", function (d) {
          return _this.cScale(values.color[d[ageDim]]);
        })
        .attr("x", 0)
        .transition().duration(duration).ease("linear")
        .attr("y", function (d) {
          return _this.yScale(values.axis_y[d[ageDim]]) - barWidth;
        })
        .attr("height", barWidth)
        .attr("width", function (d) {
          return _this.xScale(values.axis_x[d[ageDim]]);
        });

      this.labels.selectAll('.vzb-bc-label > .vzb-bc-age')
               .text(function(d) {
                  var formatter = _this.model.marker.axis_x.tickFormatter;
                  var yearOldsIn = _this.translator("popbyage/yearOldsIn");

                  var age = parseInt(values.axis_y[d[ageDim]],10);

                  if(group_by > 1) {
                    age = age + "-to-" + (age + group_by - 1);
                  }

                  return age + yearOldsIn+" "+timeFormatter(time.value) + ": "+formatter(values.axis_x[d[ageDim]]);
               })
               .attr("x", 7)
               .attr("y", function (d) {
                  return _this.yScale(values.axis_y[d[ageDim]]) - barWidth - 10;
               })
               .style("fill", function (d) {
                  var color = _this.cScale(values.color[d[ageDim]]);
                  return d3.rgb(color).darker(2);
               });

      var label = utils.values(values.label_name).reverse()[0]; //get last name

      //TODO: remove hack
      label = label === "usa" ? "United States" : "Sweden";

      this.title.text(label);

      this.year.text(this.timeFormatter(this.model.time.value));

      //update x axis again
      //TODO: remove this when grouping is done at data level
      var x_domain = this.xScale.domain();
      var x_domain_max = d3.max(utils.values(values.axis_x));
      this.xScale = this.xScale.domain([x_domain[0], x_domain_max]);
      this.resize();

    },

    /**
     * Highlight and unhighlight labels
     */
    _unhighlightBars: function() {
      this.bars.classed('vzb-dimmed', false);
      this.bars.selectAll('.vzb-bc-bar.vzb-hovered').classed('vzb-hovered', false);
      this.labels.selectAll('.vzb-hovered').classed('vzb-hovered', false);
    },

    _highlightBar: function(d) {
      this.bars.classed('vzb-dimmed', true);
      var curr =  this.bars.select("#vzb-bc-bar-"+d[this.AGEDIM]);
      curr.classed('vzb-hovered', true);
      var label = this.labels.select("#vzb-bc-label-"+d[this.AGEDIM]);
      label.classed('vzb-hovered', true);
    },

    /**
     * Select Entities
     */
    _selectBars: function() {
      var _this = this;
      var AGEDIM = this.AGEDIM;
      var selected = this.model.age.select;

      this._unselectBars();

      if(selected.length) {
        this.bars.classed('vzb-dimmed-selected', true);
        utils.forEach(selected, function(s) {
          _this.bars.select("#vzb-bc-bar-"+s[AGEDIM]).classed('vzb-selected', true);
          _this.labels.select("#vzb-bc-label-"+s[AGEDIM]).classed('vzb-selected', true);
        });
      }
    },

    _unselectBars: function() {
      this.bars.classed('vzb-dimmed-selected', false);
      this.bars.selectAll('.vzb-bc-bar.vzb-selected').classed('vzb-selected', false);
      this.labels.selectAll('.vzb-selected').classed('vzb-selected', false);
    },

    /**
     * Executes everytime the container or vizabi is resized
     * Ideally,it contains only operations related to size
     */
    resize: function () {

      var _this = this;

      this.profiles = {
        "small": {
          margin: {
            top: 70,
            right: 20,
            left: 40,
            bottom: 40
          },
          minRadius: 2,
          maxRadius: 40
        },
        "medium": {
          margin: {
            top: 80,
            right: 60,
            left: 60,
            bottom: 40
          },
          minRadius: 3,
          maxRadius: 60
        },
        "large": {
          margin: {
            top: 100,
            right: 60,
            left: 60,
            bottom: 40
          },
          minRadius: 4,
          maxRadius: 80
        }
      };

      this.activeProfile = this.profiles[this.getLayoutProfile()];
      var margin = this.activeProfile.margin;

      //stage
      this.height = parseInt(this.element.style("height"), 10) - margin.top - margin.bottom;
      this.width = parseInt(this.element.style("width"), 10) - margin.left - margin.right;

      this.graph
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      //update scales to the new range
      if (this.model.marker.axis_y.scaleType !== "ordinal") {
        this.yScale.range([this.height, 0]);
      } else {
        this.yScale.rangePoints([this.height, 0]).range();
      }
      if (this.model.marker.axis_x.scaleType !== "ordinal") {
        this.xScale.range([0, this.width]);
      } else {
        this.xScale.rangePoints([0, this.width]).range();
      }

      //apply scales to axes and redraw
      this.yAxis.scale(this.yScale)
        .orient("left")
        .tickSize(6, 0)
        .tickSizeMinor(3, 0)
        .labelerOptions({
          scaleType: this.model.marker.axis_y.scaleType,
          toolMargin: margin,
          limitMaxTickNumber: 6
        });

      this.xAxis.scale(this.xScale)
        .orient("bottom")
        .tickSize(6, 0)
        .tickSizeMinor(3, 0)
        .labelerOptions({
          scaleType: this.model.marker.axis_x.scaleType,
          toolMargin: margin,
          limitMaxTickNumber: 6
        });

      this.xAxisEl.attr("transform", "translate(0," + this.height + ")")
        .call(this.xAxis);

      this.yAxisEl.call(this.yAxis);
      this.xAxisEl.call(this.xAxis);

      this.title.attr('x', margin.right).attr('y', margin.top/2);

      this.year.attr('x', this.width + margin.left).attr('y', margin.top/2);

    }
  });

}).call(this);
<commit_msg>PA_64: Y-axis scale does not have marking at the origin.<commit_after>/*!
 * VIZABI POP BY AGE Component
 */

(function () {

  "use strict";

  var Vizabi = this.Vizabi;
  var utils = Vizabi.utils;

  //warn client if d3 is not defined
  if (!Vizabi._require('d3')) return;

  //POP BY AGE CHART COMPONENT
  Vizabi.Component.extend('gapminder-popbyage', {

    /**
     * Initializes the component (Bar Chart).
     * Executed once before any template is rendered.
     * @param {Object} config The options passed to the component
     * @param {Object} context The component's parent
     */
    init: function (config, context) {
      this.name = 'popbyage';
      this.template = 'src/tools/popbyage/popbyage.html';

      //define expected models for this component
      this.model_expects = [{
        name: "time",
        type: "time"
      }, {
        name: "entities",
        type: "entities"
      }, {
        name: "age",
        type: "entities"
      },{
        name: "marker",
        type: "model"
      }, {
        name: "language",
        type: "language"
      }];

      var _this = this;
      this.model_binds = {
        "change:time:value": function (evt) {
          _this._updateEntities();
        },
        "change:entities:show": function (evt) {
          console.log('Trying to change show');
        },
        "change:age:select": function (evt) {
          _this._selectBars();
        }
      };

      //contructor is the same as any component
      this._super(config, context);

      this.xScale = null;
      this.yScale = null;
      this.cScale = d3.scale.category10();

      this.xAxis = d3.svg.axisSmart();
      this.yAxis = d3.svg.axisSmart();
    },

    /**
     * DOM is ready
     */
    readyOnce: function () {

      this.element = d3.select(this.element);

      this.graph = this.element.select('.vzb-bc-graph');
      this.yAxisEl = this.graph.select('.vzb-bc-axis-y');
      this.xAxisEl = this.graph.select('.vzb-bc-axis-x');
      this.yTitleEl = this.graph.select('.vzb-bc-axis-y-title');
      this.bars = this.graph.select('.vzb-bc-bars');
      this.labels = this.graph.select('.vzb-bc-labels');

      this.title = this.element.select('.vzb-bc-title');
      this.year = this.element.select('.vzb-bc-year');

      //only allow selecting one at a time
      this.model.age.selectMultiple(false);

      var _this = this;
      this.on("resize", function () {
        _this._updateEntities();
      });
    },

    /*
     * Both model and DOM are ready
     */
    ready: function () {

      this.AGEDIM = this.model.age.getDimension();
      this.TIMEDIM = this.model.time.getDimension();

      this.timeFormatter = d3.time.format(this.model.time.formatOutput);

      this.updateUIStrings();
      this._updateIndicators();
      this.resize();
      this._updateEntities();
      this._updateEntities();
    },

    updateUIStrings: function(){
      this.translator = this.model.language.getTFunction();

      var titleStringY = this.translator("indicator/" + this.model.marker.axis_y.which);

      var yTitle = this.yTitleEl.selectAll("text").data([0]);
      yTitle.enter().append("text");
      yTitle
        .attr("y", "-6px")
        .attr("x", "-9px")
        .attr("dx", "-0.72em")
        .text(titleStringY);
    },

    /**
     * Changes labels for indicators
     */
    _updateIndicators: function () {
      var _this = this;
      this.duration = this.model.time.speed;

      this.yScale = this.model.marker.axis_y.getScale(false);
      this.xScale = this.model.marker.axis_x.getScale(false);
      this.cScale = this.model.marker.color.getScale();

      this.yAxis.tickFormat(_this.model.marker.axis_y.tickFormatter);
      this.xAxis.tickFormat(_this.model.marker.axis_x.tickFormatter);
    },

    /**
     * Updates entities
     */
    _updateEntities: function () {

      var _this = this;
      var time = this.model.time;
      var timeFormatter = d3.time.format(this.model.time.formatInput);
      var ageDim = this.AGEDIM;
      var timeDim = this.TIMEDIM;
      var duration = (time.playing) ? time.speed : 0;
      var filter = {};
      filter[timeDim] = time.value;
      var items = this.model.marker.getKeys(filter);
      var values = this.model.marker.getValues(filter, [ageDim]);

      //TODO: this should be done at a data layer
      //Year Grouping

      var test = function(d) {
        return parseInt(d, 10) % group_by === 1;
      }

      var group_by = this.model.marker.group_by;
      if(group_by > 1) {
        items = items.filter(function(d) {
          return test(d[ageDim]);
        });

        var new_values = {};
        utils.forEach(values, function(hook, hook_name) {
          new_values[hook_name] = {};
          var hook_values = new_values[hook_name];
          var curr = false;
          utils.forEach(hook, function(val, key) {
            if(test(key) || curr === false) {
              curr = key;
              hook_values[curr] = val;
            }
            //if it's a number and axis x
            if(!utils.isNaN(val) && hook_name === "axis_x") {
              hook_values[curr] = parseFloat(hook_values[curr]) + parseFloat(val);
            }
          });

        });

        values = new_values;

      }

      //End Year Grouping

      this.model.age.setVisible(items);

      this.entityBars = this.bars.selectAll('.vzb-bc-bar')
        .data(items);

      this.entityLabels = this.labels.selectAll('.vzb-bc-label')
        .data(items);

      //exit selection
      this.entityBars.exit().remove();
      this.entityLabels.exit().remove();

      var highlight = this._highlightBar.bind(this);
      var unhighlight = this._unhighlightBars.bind(this)

      //enter selection -- init bars
      this.entityBars.enter().append("g")
          .attr("class", "vzb-bc-bar")
          .attr("id", function(d) {
            return  "vzb-bc-bar-"+d[ageDim];
          })
          .on("mousemove", highlight)
          .on("mouseout", unhighlight)
          .on("click", function (d, i) {
            _this.model.age.selectEntity(d);
          })
          .append('rect');

      this.entityLabels.enter().append("g")
          .attr("class", "vzb-bc-label")
          .attr("id", function(d) {
            return  "vzb-bc-label-"+d[ageDim];
          })
          .on("mousemove", highlight)
          .on("mouseout", unhighlight)
          .append('text')
          .attr("class", "vzb-bc-age");

      var barWidth = this.height / items.length;

      this.bars.selectAll('.vzb-bc-bar > rect')
        .attr("fill", function (d) {
          return _this.cScale(values.color[d[ageDim]]);
        })
        .style("stroke", function (d) {
          return _this.cScale(values.color[d[ageDim]]);
        })
        .attr("x", 0)
        .transition().duration(duration).ease("linear")
        .attr("y", function (d) {
          return _this.yScale(values.axis_y[d[ageDim]]) - barWidth;
        })
        .attr("height", barWidth)
        .attr("width", function (d) {
          return _this.xScale(values.axis_x[d[ageDim]]);
        });

      this.labels.selectAll('.vzb-bc-label > .vzb-bc-age')
               .text(function(d) {
                  var formatter = _this.model.marker.axis_x.tickFormatter;
                  var yearOldsIn = _this.translator("popbyage/yearOldsIn");

                  var age = parseInt(values.axis_y[d[ageDim]],10);

                  if(group_by > 1) {
                    age = age + "-to-" + (age + group_by - 1);
                  }

                  return age + yearOldsIn+" "+timeFormatter(time.value) + ": "+formatter(values.axis_x[d[ageDim]]);
               })
               .attr("x", 7)
               .attr("y", function (d) {
                  return _this.yScale(values.axis_y[d[ageDim]]) - barWidth - 10;
               })
               .style("fill", function (d) {
                  var color = _this.cScale(values.color[d[ageDim]]);
                  return d3.rgb(color).darker(2);
               });

      var label = utils.values(values.label_name).reverse()[0]; //get last name

      //TODO: remove hack
      label = label === "usa" ? "United States" : "Sweden";

      this.title.text(label);

      this.year.text(this.timeFormatter(this.model.time.value));

      //update x axis again
      //TODO: remove this when grouping is done at data level
      var x_domain = this.xScale.domain();
      var x_domain_max = d3.max(utils.values(values.axis_x));
      this.xScale = this.xScale.domain([x_domain[0], x_domain_max]);
      this.resize();

    },

    /**
     * Highlight and unhighlight labels
     */
    _unhighlightBars: function() {
      this.bars.classed('vzb-dimmed', false);
      this.bars.selectAll('.vzb-bc-bar.vzb-hovered').classed('vzb-hovered', false);
      this.labels.selectAll('.vzb-hovered').classed('vzb-hovered', false);
    },

    _highlightBar: function(d) {
      this.bars.classed('vzb-dimmed', true);
      var curr =  this.bars.select("#vzb-bc-bar-"+d[this.AGEDIM]);
      curr.classed('vzb-hovered', true);
      var label = this.labels.select("#vzb-bc-label-"+d[this.AGEDIM]);
      label.classed('vzb-hovered', true);
    },

    /**
     * Select Entities
     */
    _selectBars: function() {
      var _this = this;
      var AGEDIM = this.AGEDIM;
      var selected = this.model.age.select;

      this._unselectBars();

      if(selected.length) {
        this.bars.classed('vzb-dimmed-selected', true);
        utils.forEach(selected, function(s) {
          _this.bars.select("#vzb-bc-bar-"+s[AGEDIM]).classed('vzb-selected', true);
          _this.labels.select("#vzb-bc-label-"+s[AGEDIM]).classed('vzb-selected', true);
        });
      }
    },

    _unselectBars: function() {
      this.bars.classed('vzb-dimmed-selected', false);
      this.bars.selectAll('.vzb-bc-bar.vzb-selected').classed('vzb-selected', false);
      this.labels.selectAll('.vzb-selected').classed('vzb-selected', false);
    },

    /**
     * Executes everytime the container or vizabi is resized
     * Ideally,it contains only operations related to size
     */
    resize: function () {

      var _this = this;

      this.profiles = {
        "small": {
          margin: {
            top: 70,
            right: 20,
            left: 40,
            bottom: 40
          },
          minRadius: 2,
          maxRadius: 40
        },
        "medium": {
          margin: {
            top: 80,
            right: 60,
            left: 60,
            bottom: 40
          },
          minRadius: 3,
          maxRadius: 60
        },
        "large": {
          margin: {
            top: 100,
            right: 60,
            left: 60,
            bottom: 40
          },
          minRadius: 4,
          maxRadius: 80
        }
      };

      this.activeProfile = this.profiles[this.getLayoutProfile()];
      var margin = this.activeProfile.margin;

      //stage
      this.height = parseInt(this.element.style("height"), 10) - margin.top - margin.bottom;
      this.width = parseInt(this.element.style("width"), 10) - margin.left - margin.right;

      this.graph
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      //update scales to the new range
      if (this.model.marker.axis_y.scaleType !== "ordinal") {
        this.yScale.range([this.height, 0]);
      } else {
        this.yScale.rangePoints([this.height, 0]).range();
      }
      if (this.model.marker.axis_x.scaleType !== "ordinal") {
        this.xScale.range([0, this.width]);
      } else {
        this.xScale.rangePoints([0, this.width]).range();
      }

      //apply scales to axes and redraw
      this.yAxis.scale(this.yScale)
        .orient("left")
        .tickSize(6, 6)
        .tickSizeMinor(3, 0)
        .labelerOptions({
          scaleType: this.model.marker.axis_y.scaleType,
          toolMargin: margin,
          limitMaxTickNumber: 6
        });

      this.xAxis.scale(this.xScale)
        .orient("bottom")
        .tickSize(6, 0)
        .tickSizeMinor(3, 0)
        .labelerOptions({
          scaleType: this.model.marker.axis_x.scaleType,
          toolMargin: margin,
          limitMaxTickNumber: 6
        });

      this.xAxisEl.attr("transform", "translate(0," + this.height + ")")
        .call(this.xAxis);

      this.yAxisEl.call(this.yAxis);
      this.xAxisEl.call(this.xAxis);

      this.title.attr('x', margin.right).attr('y', margin.top/2);

      this.year.attr('x', this.width + margin.left).attr('y', margin.top/2);

    }
  });

}).call(this);
<|endoftext|>


<commit_before>/**
 * Rainbot main file
 */

'use strict';

var logger = require('./logger');

function Bot() {
	//events
	var dispatcher = new (require('events').EventEmitter)();
	dispatcher.setMaxListeners(0); //remove listener limit
	//add empty config
	var config = new (require('./config').Config)();
	//add MM
	var moduleManager = new (require('./moduleManager').ModuleManager)(dispatcher, config);

	//load module on new listener
	dispatcher.on('newListener', function (event) {
		var i, name;
		if (((i = event.indexOf('/')) + 1) && (name = event.substr(0, i))) {
			if (!moduleManager.exists(name)) {
				//better to not load modules automagically
				//moduleManager.load(name);
				logger.warn('Added new listener (' + event + ') for not loaded module!');
			}
		}
	});

	//bot config
	this.config = config;
	this._configFile = '';
	//bot MM
	this.modules = moduleManager;
	//dispatcher
	this.dispatcher = dispatcher;

	//list of core modules
	this._coreModules = ['irc', 'controls'];

	//protect the core modules from unload
	this._coreModules.forEach(function (m) {
		moduleManager.protect(m, true);
	});

	//set to true if running
	this.__running = false;
	//set to true if halting the bot
	this.__halting = false;

	//bind to exit event of main process
	var bot = this;
	process.on('exit', function onExit() {
		if (bot.__abort) {
			return; //do nothing on abort
		}
		if (!bot.__halting) {
			bot.__halting = true;
			bot.emit('halt', bot);
		}
		bot.unloadModules();
		if (bot.config.bot && bot.config.bot.autosave && bot._configFile) {
			bot.saveConfig(bot._configFile);
		}
	});

	//shutdown on ctrl+c gracefully
	process.on('SIGINT', this.end.bind(this));

	// This will override SIGTSTP and prevent the program from going to the background.
	process.on('SIGTSTP', function () {
		process.stdout.write('[PONY] SIGTSTP DERP! Not stopping for you!\n');
	});
}

Bot.prototype.addListener = function addListener() {
	this.dispatcher.addListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.on = function on() {
	this.dispatcher.on.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.off = function off() {
	this.removeListener.apply(this, arguments);
	return this;
};

Bot.prototype.removeListener = function removeListener() {
	this.dispatcher.removeListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.once = function once() {
	this.dispatcher.once.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.emit = function emit() {
	this.dispatcher.emit.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype._checkSaneBotDefaults = function () {
	//make sure we have important values
	if (typeof this.config.bot === 'undefined') {
		this.config.bot = {
			'name': 'Rainbot',
			'modules': 'modules.json',
			'debug': false,
			'autosave': true
		};
	} else {
		if (typeof this.config.bot.name !== 'string') {
			this.config.bot.name = 'Rainbot';
		}
		if (typeof this.config.bot.modules === 'undefined') {
			this.config.bot.modules = 'modules.json';
		}
		if (typeof this.config.bot.debug !== 'boolean') {
			this.config.bot.debug = false;
		}
		if (typeof this.config.bot.autosave !== 'boolean') {
			this.config.bot.autosave = true;
		}
	}

	//set logger debuging
	logger.debugging = this.config.bot.debug ? true : false;
};

Bot.prototype.loadConfig = function loadConfig(config, merge) {
	merge = merge ? true : false;
	var error = null;

	if (typeof config === 'string') {
		this._configFile = require('path').basename(config);
	} else if (config instanceof Object) {
		this._configFile = '';
	} else {
		this._configFile = 'config.json';
	}

	try {
		if (this._configFile) {
			var cpath = require.resolve('./../' + this._configFile);
			require.cache[cpath] = null; //remove from require cache to reload
			config = require(cpath);
		}
		if (!merge) {
			this.config.clear(); //throw out old config
		}
		this.config.load(config); //load new config
		this._checkSaneBotDefaults(); //check for defaults
	} catch (e) {
		error = new Error('Cannot load config! ' + e);
	}

	if (error) {
		logger.error(error);
		logger.info('Failed to load config!');
	} else {
		logger.info('Config loaded' + (merge ? ' and merged to old config' : '') + '!');
	}

	if (!error) {
		try {
			this.modules.reloadConfig(this.config); //apply new config to modules
		} catch (e) {
			logger.error(new Error('Failed to (re)apply config to modules: ' + e));
		}
	}

	this.dispatcher.emit('config-load', error, this);

	return this;
};

Bot.prototype.saveConfig = function saveConfig(savefile, asString) {
	if (asString) {
		return JSON.stringify(this.config, null, 4);
	}

	//get only basename
	savefile = require('path').basename(savefile);

	var error = null;

	//blocking write
	try {
		var cpath = require('path').resolve(__dirname, '..', savefile);
		require('fs').writeFileSync(cpath, JSON.stringify(this.config, null, 4));
		logger.info('Config saved to \'' + savefile + '\'.');
	} catch (err) {
		error = new Error('Failed to save config with error: ' + err);
		logger.error(error);
	}

	this.dispatcher.emit('config-save', error, this);

	return this;
};

Bot.prototype.loadModules = function loadModules(modules) {
	var error = null;
	if (this.__running) {
		error = new Error('Bot is already running, please load the modules before issuing \'run\'!');
		logger.error(error);
		this.abort(error);
		return this;
	}

	if (typeof this.config.bot === 'undefined') { //we need atleast empty bot config
		this.config.bot = {
			'modules': 'modules.json'
		};
	}

	if (typeof modules === 'string') {
		this.config.bot.modules = modules;
		modules = {};
	} else if (typeof modules !== 'object' && typeof this.config.bot.modules === 'object') {
		modules = this.config.bot.modules;
	} else if (typeof modules !== 'object' && typeof this.config.bot.modules === 'string') {
		modules = {};
	} else if (typeof modules !== 'object') {
		modules = {};
		error = new Error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');
	}

	if (modules instanceof Array) {
		var tmp = modules.slice(0);
		modules = {};
		tmp.forEach(function (v) {
			modules[v] = true;
		});
	}

	if (error) { //abort
		logger.error(error);
		this.abort(error);
		return this;
	}

	//load the file
	if (Object.keys(modules).length <= 0) {
		try {
			var mpath = require.resolve('./../' + this.config.bot.modules);
			require.cache[mpath] = null; //empty require cache for this file
			modules = require(mpath);
		} catch (e) {
			modules = {};
			error = new Error('Cannot load modules file \'' + this.config.bot.modules + '\'!');
		}
	}

	//start the load of core modules
	try {
		this._coreModules.forEach(function (name) {
			this.modules.load(name);
		}, this);
	} catch (e) {
		error = e;
	}

	if (error) { //imediate abort on failure
		logger.error(error);
		this.abort(error);
		return this;
	}

	//start the load of other modules
	var keys = Object.keys(modules);
	if (keys.length > 0) {
		keys.forEach(function (name) {
			if (modules[name] === true) {
				try {
					this.modules.load(name);
				} catch (e) {
					logger.error(e);
					error = new Error('Failed loading some modules!');
				}
			}
		}, this);
	}

	logger.info('Modules loaded!');

	if (error) {
		logger.warn(error);
	}
	return this;
};

Bot.prototype.unloadModules = function unloadModules() {
	//unprotect core modules
	this._coreModules.forEach(function (name) {
		this.modules.protect(name, false);
	}, this);

	//unload all modules
	this.modules.getModules().reverse().forEach(function (m) {
		try {
			this.modules.unload(m);
		} catch (e) {
			//ignore all errors
			//just note them
			logger.warn('Caught error on module \'' + m + '\' unload: ' + e);
		}
	}, this);

	logger.info('Modules unloaded!');
	return this;
};

Bot.prototype.load = function load(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.load(name);
	}, this);

	return this;
};

Bot.prototype.unload = function unload(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.unload(name);
	}, this);

	return this;
};

Bot.prototype.reload = function reload(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.reload(name);
	}, this);

	return this;
};

Bot.prototype.run = Bot.prototype.start = function run() {
	if (this.__running) {
		return this;
	}

	logger.info('Bot initialization starting...');
	this.emit('init', this);

	this.__running = true;

	return this;
};

Bot.prototype.end = Bot.prototype.stop = function end() {
	if (!this.__halting) {
		this.__halting = true;
		this.emit('halt', this);
		logger.info('Exiting ...');
		setTimeout(process.exit, 1000); //delay it for a sec
	}

	return this;
};

Bot.prototype.abort = function abort() {
	this.__abort = true;
	process.exit(1);
	return this;
};

module.exports.Bot = Bot;
module.exports.create = function createBot() {
	return new Bot();
};
<commit_msg>dont require config<commit_after>/**
 * Rainbot main file
 */

'use strict';

var logger = require('./logger');

function Bot() {
	//events
	var dispatcher = new (require('events').EventEmitter)();
	dispatcher.setMaxListeners(0); //remove listener limit
	//add empty config
	var config = new (require('./config').Config)();
	//add MM
	var moduleManager = new (require('./moduleManager').ModuleManager)(dispatcher, config);

	//load module on new listener
	dispatcher.on('newListener', function (event) {
		var i, name;
		if (((i = event.indexOf('/')) + 1) && (name = event.substr(0, i))) {
			if (!moduleManager.exists(name)) {
				//better to not load modules automagically
				//moduleManager.load(name);
				logger.warn('Added new listener (' + event + ') for not loaded module!');
			}
		}
	});

	//bot config
	this.config = config;
	this._configFile = '';
	//bot MM
	this.modules = moduleManager;
	//dispatcher
	this.dispatcher = dispatcher;

	//list of core modules
	this._coreModules = ['irc', 'controls'];

	//protect the core modules from unload
	this._coreModules.forEach(function (m) {
		moduleManager.protect(m, true);
	});

	//set to true if running
	this.__running = false;
	//set to true if halting the bot
	this.__halting = false;

	//bind to exit event of main process
	var bot = this;
	process.on('exit', function onExit() {
		if (bot.__abort) {
			return; //do nothing on abort
		}
		if (!bot.__halting) {
			bot.__halting = true;
			bot.emit('halt', bot);
		}
		bot.unloadModules();
		if (bot.config.bot && bot.config.bot.autosave && bot._configFile) {
			bot.saveConfig(bot._configFile);
		}
	});

	//shutdown on ctrl+c gracefully
	process.on('SIGINT', this.end.bind(this));

	// This will override SIGTSTP and prevent the program from going to the background.
	process.on('SIGTSTP', function () {
		process.stdout.write('[PONY] SIGTSTP DERP! Not stopping for you!\n');
	});
}

Bot.prototype.addListener = function addListener() {
	this.dispatcher.addListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.on = function on() {
	this.dispatcher.on.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.off = function off() {
	this.removeListener.apply(this, arguments);
	return this;
};

Bot.prototype.removeListener = function removeListener() {
	this.dispatcher.removeListener.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.once = function once() {
	this.dispatcher.once.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype.emit = function emit() {
	this.dispatcher.emit.apply(this.dispatcher, arguments);
	return this;
};

Bot.prototype._checkSaneBotDefaults = function () {
	//make sure we have important values
	if (typeof this.config.bot === 'undefined') {
		this.config.bot = {
			'name': 'Rainbot',
			'modules': 'modules.json',
			'debug': false,
			'autosave': true
		};
	} else {
		if (typeof this.config.bot.name !== 'string') {
			this.config.bot.name = 'Rainbot';
		}
		if (typeof this.config.bot.modules === 'undefined') {
			this.config.bot.modules = 'modules.json';
		}
		if (typeof this.config.bot.debug !== 'boolean') {
			this.config.bot.debug = false;
		}
		if (typeof this.config.bot.autosave !== 'boolean') {
			this.config.bot.autosave = true;
		}
	}

	//set logger debuging
	logger.debugging = this.config.bot.debug ? true : false;
};

Bot.prototype.loadConfig = function loadConfig(config, merge) {
	merge = merge ? true : false;
	var error = null;

	if (typeof config === 'string') {
		this._configFile = require('path').basename(config);
	} else if (config instanceof Object) {
		this._configFile = '';
	} else {
		this._configFile = 'config.json';
	}

	try {
		if (this._configFile) {
			var cpath = require('path').resolve(__dirname, '..', this._configFile);
			try {
				config = JSON.parse(require('fs').readFileSync(cpath).toString());
			} catch (e) {
				config = {};
			}
		}
		if (!merge) {
			this.config.clear(); //throw out old config
		}
		this.config.load(config); //load new config
		this._checkSaneBotDefaults(); //check for defaults
	} catch (e) {
		error = new Error('Cannot load config! ' + e);
	}

	if (error) {
		logger.error(error);
		logger.info('Failed to load config!');
	} else {
		logger.info('Config loaded' + (merge ? ' and merged to old config' : '') + '!');
	}

	if (!error) {
		try {
			this.modules.reloadConfig(this.config); //apply new config to modules
		} catch (e) {
			logger.error(new Error('Failed to (re)apply config to modules: ' + e));
		}
	}

	this.dispatcher.emit('config-load', error, this);

	return this;
};

Bot.prototype.saveConfig = function saveConfig(savefile, asString) {
	if (asString) {
		return JSON.stringify(this.config, null, 4);
	}

	//get only basename
	savefile = require('path').basename(savefile);

	var error = null;

	//blocking write
	try {
		var cpath = require('path').resolve(__dirname, '..', savefile);
		require('fs').writeFileSync(cpath, JSON.stringify(this.config, null, 4));
		logger.info('Config saved to \'' + savefile + '\'.');
	} catch (err) {
		error = new Error('Failed to save config with error: ' + err);
		logger.error(error);
	}

	this.dispatcher.emit('config-save', error, this);

	return this;
};

Bot.prototype.loadModules = function loadModules(modules) {
	var error = null;
	if (this.__running) {
		error = new Error('Bot is already running, please load the modules before issuing \'run\'!');
		logger.error(error);
		this.abort(error);
		return this;
	}

	if (typeof this.config.bot === 'undefined') { //we need atleast empty bot config
		this.config.bot = {
			'modules': 'modules.json'
		};
	}

	if (typeof modules === 'string') {
		this.config.bot.modules = modules;
		modules = {};
	} else if (typeof modules !== 'object' && typeof this.config.bot.modules === 'object') {
		modules = this.config.bot.modules;
	} else if (typeof modules !== 'object' && typeof this.config.bot.modules === 'string') {
		modules = {};
	} else if (typeof modules !== 'object') {
		modules = {};
		error = new Error('Modules was nor Object nor Array nor String! Trying to load default \'modules.json\'.');
	}

	if (modules instanceof Array) {
		var tmp = modules.slice(0);
		modules = {};
		tmp.forEach(function (v) {
			modules[v] = true;
		});
	}

	if (error) { //abort
		logger.error(error);
		this.abort(error);
		return this;
	}

	//load the file
	if (Object.keys(modules).length <= 0) {
		try {
			var mpath = require.resolve('./../' + this.config.bot.modules);
			require.cache[mpath] = null; //empty require cache for this file
			modules = require(mpath);
		} catch (e) {
			modules = {};
			error = new Error('Cannot load modules file \'' + this.config.bot.modules + '\'!');
		}
	}

	//start the load of core modules
	try {
		this._coreModules.forEach(function (name) {
			this.modules.load(name);
		}, this);
	} catch (e) {
		error = e;
	}

	if (error) { //imediate abort on failure
		logger.error(error);
		this.abort(error);
		return this;
	}

	//start the load of other modules
	var keys = Object.keys(modules);
	if (keys.length > 0) {
		keys.forEach(function (name) {
			if (modules[name] === true) {
				try {
					this.modules.load(name);
				} catch (e) {
					logger.error(e);
					error = new Error('Failed loading some modules!');
				}
			}
		}, this);
	}

	logger.info('Modules loaded!');

	if (error) {
		logger.warn(error);
	}
	return this;
};

Bot.prototype.unloadModules = function unloadModules() {
	//unprotect core modules
	this._coreModules.forEach(function (name) {
		this.modules.protect(name, false);
	}, this);

	//unload all modules
	this.modules.getModules().reverse().forEach(function (m) {
		try {
			this.modules.unload(m);
		} catch (e) {
			//ignore all errors
			//just note them
			logger.warn('Caught error on module \'' + m + '\' unload: ' + e);
		}
	}, this);

	logger.info('Modules unloaded!');
	return this;
};

Bot.prototype.load = function load(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.load(name);
	}, this);

	return this;
};

Bot.prototype.unload = function unload(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.unload(name);
	}, this);

	return this;
};

Bot.prototype.reload = function reload(names) {
	if (!(names instanceof Array)) {
		names = [names];
	}

	names.forEach(function (name) {
		this.modules.reload(name);
	}, this);

	return this;
};

Bot.prototype.run = Bot.prototype.start = function run() {
	if (this.__running) {
		return this;
	}

	logger.info('Bot initialization starting...');
	this.emit('init', this);

	this.__running = true;

	return this;
};

Bot.prototype.end = Bot.prototype.stop = function end() {
	if (!this.__halting) {
		this.__halting = true;
		this.emit('halt', this);
		logger.info('Exiting ...');
		setTimeout(process.exit, 1000); //delay it for a sec
	}

	return this;
};

Bot.prototype.abort = function abort() {
	this.__abort = true;
	process.exit(1);
	return this;
};

module.exports.Bot = Bot;
module.exports.create = function createBot() {
	return new Bot();
};
<|endoftext|>


<commit_before>const { Command } = require('discord.js-commando');

const Currency = require('../../currency/Currency');
const Inventory = require('../../currency/Inventory');
const ItemGroup = require('../../currency/ItemGroup');

module.exports = class ItemTradeCommand extends Command {
	constructor(client) {
		super(client, {
			name: 'item-trade',
			aliases: ['trade-items', 'trade-item', 'items-trade'],
			group: 'item',
			memberName: 'trade',
			description: `Trade items with another user.`,
			guildOnly: true,
			throttling: {
				usages: 2,
				duration: 3
			},

			args: [
				{
					key: 'member',
					prompt: 'what user would you like to give your item(s)?\n',
					type: 'member'
				},
				{
					key: 'offerItem',
					prompt: 'what item would you like to trade?\n',
					type: 'string'
				},
				{
					key: 'offerAmount',
					label: 'amount of items to give',
					prompt: 'how many would you like to trade?\n',
					type: 'integer',
					min: 1
				},
				{
					key: 'receiveItem',
					prompt: 'what item would you like to receive?\n',
					type: 'string'
				},
				{
					key: 'receiveAmount',
					label: 'amount of items to receive',
					prompt: 'how many items would you like to receive?\n',
					type: 'integer',
					min: 1
				}
			]
		});
	}

	async run(msg, args) {
		const user = args.member;
		const offerItem = this.isDonuts(args.offerItem, offerAmount);
		const offerAmount = args.offerAmount;
		const receiveItem = this.isDonuts(args.receiveItem, receiveAmount);
		const receiveAmount = args.receiveAmount;

		if (user.id === msg.author.id) return msg.reply('what are you trying to achieve by trading with yourself?');
		if (user.user.bot) return msg.reply('bots got nothing to trade, man.');
		if (!offerItem && !receiveItem) return msg.reply("you can't trade donuts for donuts.");

		const offerBalance = Currency.getBalance(msg.author.id);
		const receiveBalance = Currency.getBalance(user.id);
		const offerInv = Inventory.fetchInventory(msg.author.id);
		const receiveInv = Inventory.fetchInventory(user.id);
		const offerItemBalance = offerInv.content[offerItem] ? offerInv.content[offerItem].amount : null;
		const receiveItemBalance = receiveInv.content[receiveItem] ? receiveInv.content[receiveItem].amount : null;

		const offerValidation = this.validate(offerItem, offerAmount, offerBalance, offerItemBalance, 'you');
		const receiveValidation = this.validate(receiveItem, receiveAmount, receiveBalance, receiveItemBalance, user.displayName);
		if (offerValidation) return msg.reply(offerValidation);
		if (receiveValidation) return msg.reply(receiveValidation);

		const embed = {
			title: `${msg.member.displayName} < -- > ${user.displayName}`,
			description: 'Type `accept` within the next 30 seconds to accept this trade.',
			fields: [
				{
					name: msg.member.displayName,
					value: offerItem
						? `${offerAmount} ${offerItem}`
						: Currency.convert(offerAmount)
				},
				{
					name: user.displayName,
					value: receiveItem
						? `${receiveAmount} ${receiveItem}`
						: Currency.convert(receiveAmount)
				}
			]
		};

		if (!await this.response(msg, user, embed)) return msg.reply(`${user.displayName} declined or failed to respond.`);

		if (!offerItem) this.sendDonuts(msg.author, user, offerAmount);
		else this.sendItems(offerInv, receiveInv, offerItem, offerAmount);

		if (!receiveItem) this.sendDonuts(user, msg.author, receiveAmount);
		else this.sendItems(receiveInv, offerInv, receiveItem, receiveAmount);

		return msg.say('Trade successful.');
	}

	validate(item, amount, balance, itemBalance, user) {
		const person = user === 'you';

		if (item) {
			if (!itemBalance) return `${user} ${person ? "don't" : "doesn't"} have any ${item}s.`;
			if (amount > itemBalance) return `${user} ${person ? 'have' : 'has'} only ${itemBalance} ${item}s.`;
		} else if (amount > balance) {
			return `${user} ${person ? 'have' : 'has'} only ${Currency.convert(balance)}`;
		}

		return null;
	}

	isDonuts(item, amount) {
		if (/donuts?/.test(item)) return null;

		return ItemGroup.convert(item, amount);
	}

	sendItems(fromInventory, toInventory, item, amount) {
		const itemGroup = new ItemGroup(item, amount);

		fromInventory.removeItems(itemGroup);
		toInventory.addItems(itemGroup);
	}

	sendDonuts(fromUser, toUser, amount) {
		Currency.removeBalance(fromUser, amount);
		Currency.addBalance(toUser, amount);
	}

	response(msg, user, embed) {
		return new Promise(async resolve => {
			msg.say(`${user}, ${msg.member.displayName} wants to trade with you.`);
			msg.embed(embed);

			const responses = await msg.channel.awaitMessages(response => {
				return response.author.id === user.id && response.content.toLowerCase() === 'accept';
			}, {
				maxMatches: 1,
				time: 30e3
			});

			if (responses.size === 0) return resolve(false);

			return resolve(true);
		});
	}
};
<commit_msg>Fix my derp<commit_after>const { Command } = require('discord.js-commando');

const Currency = require('../../currency/Currency');
const Inventory = require('../../currency/Inventory');
const ItemGroup = require('../../currency/ItemGroup');

module.exports = class ItemTradeCommand extends Command {
	constructor(client) {
		super(client, {
			name: 'item-trade',
			aliases: ['trade-items', 'trade-item', 'items-trade'],
			group: 'item',
			memberName: 'trade',
			description: `Trade items with another user.`,
			guildOnly: true,
			throttling: {
				usages: 2,
				duration: 3
			},

			args: [
				{
					key: 'member',
					prompt: 'what user would you like to give your item(s)?\n',
					type: 'member'
				},
				{
					key: 'offerItem',
					prompt: 'what item would you like to trade?\n',
					type: 'string'
				},
				{
					key: 'offerAmount',
					label: 'amount of items to give',
					prompt: 'how many would you like to trade?\n',
					type: 'integer',
					min: 1
				},
				{
					key: 'receiveItem',
					prompt: 'what item would you like to receive?\n',
					type: 'string'
				},
				{
					key: 'receiveAmount',
					label: 'amount of items to receive',
					prompt: 'how many items would you like to receive?\n',
					type: 'integer',
					min: 1
				}
			]
		});
	}

	async run(msg, args) {
		const user = args.member;
		const offerAmount = args.offerAmount;
		const receiveAmount = args.receiveAmount;
		const offerItem = this.isDonuts(args.offerItem, offerAmount);
		const receiveItem = this.isDonuts(args.receiveItem, receiveAmount);

		if (user.id === msg.author.id) return msg.reply('what are you trying to achieve by trading with yourself?');
		if (user.user.bot) return msg.reply('bots got nothing to trade, man.');
		if (!offerItem && !receiveItem) return msg.reply("you can't trade donuts for donuts.");

		const offerBalance = Currency.getBalance(msg.author.id);
		const receiveBalance = Currency.getBalance(user.id);
		const offerInv = Inventory.fetchInventory(msg.author.id);
		const receiveInv = Inventory.fetchInventory(user.id);
		const offerItemBalance = offerInv.content[offerItem] ? offerInv.content[offerItem].amount : null;
		const receiveItemBalance = receiveInv.content[receiveItem] ? receiveInv.content[receiveItem].amount : null;

		const offerValidation = this.validate(offerItem, offerAmount, offerBalance, offerItemBalance, 'you');
		const receiveValidation = this.validate(receiveItem, receiveAmount, receiveBalance, receiveItemBalance, user.displayName);
		if (offerValidation) return msg.reply(offerValidation);
		if (receiveValidation) return msg.reply(receiveValidation);

		const embed = {
			title: `${msg.member.displayName} < -- > ${user.displayName}`,
			description: 'Type `accept` within the next 30 seconds to accept this trade.',
			fields: [
				{
					name: msg.member.displayName,
					value: offerItem
						? `${offerAmount} ${offerItem}`
						: Currency.convert(offerAmount)
				},
				{
					name: user.displayName,
					value: receiveItem
						? `${receiveAmount} ${receiveItem}`
						: Currency.convert(receiveAmount)
				}
			]
		};

		if (!await this.response(msg, user, embed)) return msg.reply(`${user.displayName} declined or failed to respond.`);

		if (!offerItem) this.sendDonuts(msg.author, user, offerAmount);
		else this.sendItems(offerInv, receiveInv, offerItem, offerAmount);

		if (!receiveItem) this.sendDonuts(user, msg.author, receiveAmount);
		else this.sendItems(receiveInv, offerInv, receiveItem, receiveAmount);

		return msg.say('Trade successful.');
	}

	validate(item, amount, balance, itemBalance, user) {
		const person = user === 'you';

		if (item) {
			if (!itemBalance) return `${user} ${person ? "don't" : "doesn't"} have any ${item}s.`;
			if (amount > itemBalance) return `${user} ${person ? 'have' : 'has'} only ${itemBalance} ${item}s.`;
		} else if (amount > balance) {
			return `${user} ${person ? 'have' : 'has'} only ${Currency.convert(balance)}`;
		}

		return null;
	}

	isDonuts(item, amount) {
		if (/donuts?/.test(item)) return null;

		return ItemGroup.convert(item, amount);
	}

	sendItems(fromInventory, toInventory, item, amount) {
		const itemGroup = new ItemGroup(item, amount);

		fromInventory.removeItems(itemGroup);
		toInventory.addItems(itemGroup);
	}

	sendDonuts(fromUser, toUser, amount) {
		Currency.removeBalance(fromUser, amount);
		Currency.addBalance(toUser, amount);
	}

	response(msg, user, embed) {
		return new Promise(async resolve => {
			msg.say(`${user}, ${msg.member.displayName} wants to trade with you.`);
			msg.embed(embed);

			const responses = await msg.channel.awaitMessages(response => {
				return response.author.id === user.id && response.content.toLowerCase() === 'accept';
			}, {
				maxMatches: 1,
				time: 30e3
			});

			if (responses.size === 0) return resolve(false);

			return resolve(true);
		});
	}
};
<|endoftext|>


<commit_before>// @flow

import minimatch from 'minimatch';
import sortBy from 'lodash.sortby';
import uniqBy from 'lodash.uniqby';

import Configuration from './Configuration';
import JsModule from './JsModule';
import ModuleFinder from './ModuleFinder';

function findImportsFromEnvironment(
  config: Configuration,
  variableName: string,
): Array<JsModule> {
  return config
    .get('coreModules')
    .filter(
      (dep: string): boolean =>
        dep.toLowerCase() === variableName.toLowerCase(),
    )
    .map(
      (dep: string): JsModule => new JsModule({
        importPath: dep,
        variableName,
      }),
    );
}

function findJsModulesFromModuleFinder(
  config: Configuration,
  normalizedName: string,
  variableName: string,
  finder: ModuleFinder,
  pathToCurrentFile: string,
  options: Object = {},
): Promise<Array<JsModule>> {
  return new Promise((resolve: Function, reject: Function) => {
    let isWantedPackageDependency = Boolean;
    if (!config.get('importDevDependencies')) {
      const packageDependencies = config.get('packageDependencies');
      isWantedPackageDependency = (packageName: string): boolean =>
        packageDependencies.has(packageName);
    }

    const isSearch = !!options.search;
    const method = isSearch ? 'search' : 'find';

    finder[method](normalizedName)
      .then((exports: Array<Object>) => {
        const modules = exports.map((
          { name, path, isDefault, packageName }: Object,
        ): ?JsModule => {
          // Filter out modules that are in the `excludes` config.
          if (config.get('excludes').some((glob: string): boolean =>
            minimatch(path, glob))) {
            return undefined;
          }

          if (packageName) {
            if (!isWantedPackageDependency(packageName)) {
              return undefined;
            }
            return new JsModule({
              importPath: packageName,
              variableName: isSearch ? name : variableName,
              hasNamedExports: !isDefault,
            });
          }

          return JsModule.construct({
            hasNamedExports: !isDefault,
            relativeFilePath: path,
            stripFileExtensions: config.get('stripFileExtensions', {
              pathToImportedModule: path,
            }),
            makeRelativeTo: config.get('useRelativePaths', {
              pathToImportedModule: path,
            }) &&
              config.pathToCurrentFile,
            variableName: isSearch ? name : variableName,
            workingDirectory: config.workingDirectory,
          });
        });
        resolve(modules.filter(Boolean));
      })
      .catch(reject);
  });
}

function dedupeAndSort(modules: Array<JsModule>): Array<JsModule> {
  // We might end up having duplicate modules here.  In order to dedupe
  // these, we remove the module with the longest path
  const sorted = sortBy(
    modules,
    (module: JsModule): number => module.importPath.length,
  );
  const uniques = uniqBy(
    sorted,
    (module: JsModule): string => module.importPath,
  );
  return sortBy(uniques, (module: JsModule): string => module.displayName());
}

const NON_PATH_ALIAS_PATTERN = /^[a-zA-Z0-9-_]+$/;

type FindJsModulesForOptionsType = {
  search: boolean,
};

export default function findJsModulesFor(
  config: Configuration,
  variableName: string,
  options?: FindJsModulesForOptionsType,
): Promise<Array<JsModule>> {
  return new Promise((resolve: Function, reject: Function) => {
    let normalizedName = variableName;
    const alias = config.resolveAlias(variableName);
    if (alias) {
      if (NON_PATH_ALIAS_PATTERN.test(alias)) {
        // The alias is likely a package dependency. We can use it in the
        // ModuleFinder lookup.
        normalizedName = alias;
      } else {
        // The alias is a path of some sort. Use it directly as the moduleName
        // in the import.
        resolve([new JsModule({ importPath: alias, variableName })]);
        return;
      }
    }

    const namedImportsModule = config.resolveNamedExports(variableName);
    if (namedImportsModule) {
      resolve([namedImportsModule]);
      return;
    }

    const matchedModules = [];

    matchedModules.push(...findImportsFromEnvironment(config, variableName));

    const finder = ModuleFinder.getForWorkingDirectory(
      config.workingDirectory,
      {
        excludes: config.get('excludes'),
        ignorePackagePrefixes: config.get('ignorePackagePrefixes'),
      },
    );
    findJsModulesFromModuleFinder(
      config,
      normalizedName,
      variableName,
      finder,
      config.pathToCurrentFile,
      options,
    )
      .then((modules: Array<JsModule>) => {
        matchedModules.push(...modules);
        resolve(dedupeAndSort(matchedModules));
      })
      .catch((error: Object) => {
        reject(error);
      });
  });
}
<commit_msg>Improve readability of exclusion check in findJsModulesFor<commit_after>// @flow

import minimatch from 'minimatch';
import sortBy from 'lodash.sortby';
import uniqBy from 'lodash.uniqby';

import Configuration from './Configuration';
import JsModule from './JsModule';
import ModuleFinder from './ModuleFinder';

function findImportsFromEnvironment(
  config: Configuration,
  variableName: string,
): Array<JsModule> {
  return config
    .get('coreModules')
    .filter(
      (dep: string): boolean =>
        dep.toLowerCase() === variableName.toLowerCase(),
    )
    .map(
      (dep: string): JsModule => new JsModule({
        importPath: dep,
        variableName,
      }),
    );
}

function findJsModulesFromModuleFinder(
  config: Configuration,
  normalizedName: string,
  variableName: string,
  finder: ModuleFinder,
  pathToCurrentFile: string,
  options: Object = {},
): Promise<Array<JsModule>> {
  return new Promise((resolve: Function, reject: Function) => {
    let isWantedPackageDependency = Boolean;
    if (!config.get('importDevDependencies')) {
      const packageDependencies = config.get('packageDependencies');
      isWantedPackageDependency = (packageName: string): boolean =>
        packageDependencies.has(packageName);
    }

    const isSearch = !!options.search;
    const method = isSearch ? 'search' : 'find';

    finder[method](normalizedName)
      .then((exports: Array<Object>) => {
        const modules = exports.map((
          { name, path, isDefault, packageName }: Object,
        ): ?JsModule => {
          // Filter out modules that are in the `excludes` config.
          const isExcluded = config.get('excludes')
            .some((glob: string): boolean => minimatch(path, glob));
          if (isExcluded) {
            return undefined;
          }

          if (packageName) {
            if (!isWantedPackageDependency(packageName)) {
              return undefined;
            }
            return new JsModule({
              importPath: packageName,
              variableName: isSearch ? name : variableName,
              hasNamedExports: !isDefault,
            });
          }

          return JsModule.construct({
            hasNamedExports: !isDefault,
            relativeFilePath: path,
            stripFileExtensions: config.get('stripFileExtensions', {
              pathToImportedModule: path,
            }),
            makeRelativeTo: config.get('useRelativePaths', {
              pathToImportedModule: path,
            }) &&
              config.pathToCurrentFile,
            variableName: isSearch ? name : variableName,
            workingDirectory: config.workingDirectory,
          });
        });
        resolve(modules.filter(Boolean));
      })
      .catch(reject);
  });
}

function dedupeAndSort(modules: Array<JsModule>): Array<JsModule> {
  // We might end up having duplicate modules here.  In order to dedupe
  // these, we remove the module with the longest path
  const sorted = sortBy(
    modules,
    (module: JsModule): number => module.importPath.length,
  );
  const uniques = uniqBy(
    sorted,
    (module: JsModule): string => module.importPath,
  );
  return sortBy(uniques, (module: JsModule): string => module.displayName());
}

const NON_PATH_ALIAS_PATTERN = /^[a-zA-Z0-9-_]+$/;

type FindJsModulesForOptionsType = {
  search: boolean,
};

export default function findJsModulesFor(
  config: Configuration,
  variableName: string,
  options?: FindJsModulesForOptionsType,
): Promise<Array<JsModule>> {
  return new Promise((resolve: Function, reject: Function) => {
    let normalizedName = variableName;
    const alias = config.resolveAlias(variableName);
    if (alias) {
      if (NON_PATH_ALIAS_PATTERN.test(alias)) {
        // The alias is likely a package dependency. We can use it in the
        // ModuleFinder lookup.
        normalizedName = alias;
      } else {
        // The alias is a path of some sort. Use it directly as the moduleName
        // in the import.
        resolve([new JsModule({ importPath: alias, variableName })]);
        return;
      }
    }

    const namedImportsModule = config.resolveNamedExports(variableName);
    if (namedImportsModule) {
      resolve([namedImportsModule]);
      return;
    }

    const matchedModules = [];

    matchedModules.push(...findImportsFromEnvironment(config, variableName));

    const finder = ModuleFinder.getForWorkingDirectory(
      config.workingDirectory,
      {
        excludes: config.get('excludes'),
        ignorePackagePrefixes: config.get('ignorePackagePrefixes'),
      },
    );
    findJsModulesFromModuleFinder(
      config,
      normalizedName,
      variableName,
      finder,
      config.pathToCurrentFile,
      options,
    )
      .then((modules: Array<JsModule>) => {
        matchedModules.push(...modules);
        resolve(dedupeAndSort(matchedModules));
      })
      .catch((error: Object) => {
        reject(error);
      });
  });
}
<|endoftext|>