<commit_before>// load all defined plugins

var logger      = require('./logger');
var config      = require('./config');
var constants   = require('./constants');
var path        = require('path');

var plugin_path = process.env.HARAKA ? path.join(process.env.HARAKA, 'plugins') : './plugins';
// These are the hooks that qpsmtpd implements - I should get around
// to supporting them all some day... :-/
var hooks = [
    'connect',
    'pre-connection',
    'connect',
    'ehlo_parse',
    'ehlo',
    'helo_parse',
    'helo',
    'auth_parse',
    'auth',
    'auth-plain',
    'auth-login',
    'auth-cram-md5',
    'rcpt_parse',
    'rcpt_pre',
    'rcpt',
    'mail_parse',
    'mail',
    'mail_pre',
    'data',
    'data_headers_end',
    'data_post',
    'queue_pre',
    'queue',
    'queue_post',
    'vrfy',
    'noop',
    'quit',
    'reset_transaction',
    'disconnect',
    'post-connection',
    'unrecognized_command',
    'deny',
    'ok',
    'received_line',
    'help'
];

function Plugin(name) {
    this.name = name;
    this.full_path = path.resolve(plugin_path, name);
    this.hooks = {};
};

Plugin.prototype.register_hook = function(hook_name, method_name) {
    this.hooks[hook_name] = this.hooks[hook_name] || [];
    this.hooks[hook_name].push(method_name);

    logger.logdebug("registered hook " + hook_name + " to " + this.name + "." + method_name);
}

// copy logger methods into Plugin:

for (var key in logger) {
    if (key.match(/^log\w/)) {
        // console.log("adding Plugin." + key + " method");
        var key_copy = key.slice(0);
        eval("Plugin.prototype." + key_copy + " = function (data) { logger." + key_copy + "(\"[\" + this.name + \"] \" + data); }");
    }
}

var plugins = exports;

plugins.load_plugins = function () {
    logger.loginfo("Loading plugins");
    var plugin_list = config.get('plugins');

    plugins.plugin_list = plugin_list.map(plugins.load_plugin);
};

plugins.load_plugin = function(name) {
    logger.loginfo("Loading plugin: " + name);

    var plugin = new Plugin(name);

    var plugin_methods = require(plugin.full_path);

    // copy the plugins' export methods into this new instance.
    for (var method in plugin_methods) {
        if (plugin[method]) {
            // Method already exists
            logger.logcrit("Method " + method + " already exists in Plugin class while loading plugin " + name);
        }
        plugin[method] = plugin_methods[method];
    }

    plugin.register();

    return plugin;
}

plugins.load_plugins();

plugins.run_hooks = function (hook, connection, params) {
    if (!params) params = [];

    logger.logdebug("running " + hook + " hooks");

    connection.hooks_to_run = [];

    for (i = 0; i < plugins.plugin_list.length; i++) {
        var plugin = plugins.plugin_list[i];

        if (plugin.hooks[hook]) {
            var j;
            for (j = 0; j < plugin.hooks[hook].length; j++) {
                var hook_code_name = plugin.hooks[hook][j];
                connection.hooks_to_run.push([plugin, hook_code_name]);
            }
        }
    }

    plugins.run_next_hook(hook, connection, params);
};

plugins.run_next_hook = function(hook, connection, params) {
    var called_once = 0;
    var callback = function(retval, msg) {
        if (called_once) {
            logger.logerror("callback called multiple times. Ignoring subsequent calls");
            return;
        }
        called_once++;
        if (!retval) retval = constants.cont;
        if (connection.hooks_to_run.length == 0 ||
            retval !== constants.cont)
        {
            var respond_method = hook + "_respond";
            connection[respond_method](retval, msg);
        }
        else {
            plugins.run_next_hook(hook, connection, params);
        }
    }

    if (!connection.hooks_to_run.length) return callback();

    // shift the next one off the stack and run it.
    var item = connection.hooks_to_run.shift();
    item[0][ item[1] ].call(item[0], callback, connection, params);
};

<commit_msg>Allow plugins to have hooks of just hook_blah like qpsmtpd<commit_after>// load all defined plugins

var logger      = require('./logger');
var config      = require('./config');
var constants   = require('./constants');
var path        = require('path');

var plugin_path = process.env.HARAKA ? path.join(process.env.HARAKA, 'plugins') : './plugins';
// These are the hooks that qpsmtpd implements - I should get around
// to supporting them all some day... :-/
var hooks = [
    'connect',
    'pre-connection',
    'connect',
    'ehlo_parse',
    'ehlo',
    'helo_parse',
    'helo',
    'auth_parse',
    'auth',
    'auth-plain',
    'auth-login',
    'auth-cram-md5',
    'rcpt_parse',
    'rcpt_pre',
    'rcpt',
    'mail_parse',
    'mail',
    'mail_pre',
    'data',
    'data_headers_end',
    'data_post',
    'queue_pre',
    'queue',
    'queue_post',
    'vrfy',
    'noop',
    'quit',
    'reset_transaction',
    'disconnect',
    'post-connection',
    'unrecognized_command',
    'deny',
    'ok',
    'received_line',
    'help'
];

function Plugin(name) {
    this.name = name;
    this.full_path = path.resolve(plugin_path, name);
    this.config = config;
    this.hooks = {};
};

Plugin.prototype.register_hook = function(hook_name, method_name) {
    this.hooks[hook_name] = this.hooks[hook_name] || [];
    this.hooks[hook_name].push(method_name);

    logger.logdebug("registered hook " + hook_name + " to " + this.name + "." + method_name);
}

// copy logger methods into Plugin:

for (var key in logger) {
    if (key.match(/^log\w/)) {
        // console.log("adding Plugin." + key + " method");
        var key_copy = key.slice(0);
        eval("Plugin.prototype." + key_copy + " = function (data) { logger." + key_copy + "(\"[\" + this.name + \"] \" + data); }");
    }
}

var plugins = exports;

plugins.load_plugins = function () {
    logger.loginfo("Loading plugins");
    var plugin_list = config.get('plugins');

    plugins.plugin_list = plugin_list.map(plugins.load_plugin);
};

plugins.load_plugin = function(name) {
    logger.loginfo("Loading plugin: " + name);

    var plugin = new Plugin(name);

    var plugin_methods = require(plugin.full_path);

    // copy the plugins' export methods into this new instance.
    for (var method in plugin_methods) {
        if (plugin[method]) {
            // Method already exists
            logger.logcrit("Method " + method + " already exists in Plugin class while loading plugin " + name);
        }
        plugin[method] = plugin_methods[method];
        var result;
        if (result = method.match(/^hook_(\w+)\b/)) {
            plugin.register_hook(result[1], method);
        }
    }

    if (plugin.register) {
        plugin.register();
    }

    return plugin;
}

plugins.load_plugins();

plugins.run_hooks = function (hook, connection, params) {
    if (!params) params = [];

    logger.logdebug("running " + hook + " hooks");

    connection.hooks_to_run = [];

    for (i = 0; i < plugins.plugin_list.length; i++) {
        var plugin = plugins.plugin_list[i];

        if (plugin.hooks[hook]) {
            var j;
            for (j = 0; j < plugin.hooks[hook].length; j++) {
                var hook_code_name = plugin.hooks[hook][j];
                connection.hooks_to_run.push([plugin, hook_code_name]);
            }
        }
    }

    plugins.run_next_hook(hook, connection, params);
};

plugins.run_next_hook = function(hook, connection, params) {
    var called_once = 0;
    var callback = function(retval, msg) {
        if (called_once) {
            logger.logerror("callback called multiple times. Ignoring subsequent calls");
            return;
        }
        called_once++;
        if (!retval) retval = constants.cont;
        if (connection.hooks_to_run.length == 0 ||
            retval !== constants.cont)
        {
            var respond_method = hook + "_respond";
            connection[respond_method](retval, msg);
        }
        else {
            plugins.run_next_hook(hook, connection, params);
        }
    }

    if (!connection.hooks_to_run.length) return callback();

    // shift the next one off the stack and run it.
    var item = connection.hooks_to_run.shift();
    try {
        item[0][ item[1] ].call(item[0], callback, connection, params);
    }
    catch (err) {
        logger.logcrit("Plugin " + item[0].name + " failed: " + err);
        callback();
    }
};

<|endoftext|>


<commit_before>var bundleFn = arguments[3];
var sources = arguments[4];
var cache = arguments[5];

var stringify = JSON.stringify;

module.exports = function (fn) {
    var keys = [];
    var wkey;
    var cacheKeys = Object.keys(cache);

    for (var i = 0, l = cacheKeys.length; i < l; i++) {
        var key = cacheKeys[i];
        var exp = cache[key].exports;
        // Using babel as a transpiler to use esmodule, the export will always
        // be an object with the default export as a property of it. To ensure
        // the existing api and babel esmodule exports are both supported we
        // check for both
        if (exp === fn || exp.default === fn) {
            wkey = key;
            break;
        }
    }

    if (!wkey) {
        wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
        var wcache = {};
        for (var i = 0, l = cacheKeys.length; i < l; i++) {
            var key = cacheKeys[i];
            wcache[key] = key;
        }
        sources[wkey] = [
            Function(['require','module','exports'], '(' + fn + ')(self)'),
            wcache
        ];
    }
    var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);

    var scache = {}; scache[wkey] = wkey;
    sources[skey] = [
        Function(['require'], (
            // try to call default if defined to also support babel esmodule
            // exports
            'var f = require(' + stringify(wkey) + ');' +
            '(f.default ? f.default : f)(self);'
        )),
        scache
    ];

    var src = '(' + bundleFn + ')({'
        + Object.keys(sources).map(function (key) {
            return stringify(key) + ':['
                + sources[key][0]
                + ',' + stringify(sources[key][1]) + ']'
            ;
        }).join(',')
        + '},{},[' + stringify(skey) + '])'
    ;

    var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

    return new Worker(URL.createObjectURL(
        new Blob([src], { type: 'text/javascript' })
    ));
};
<commit_msg>Remove keys array variable. Declared but never used.<commit_after>var bundleFn = arguments[3];
var sources = arguments[4];
var cache = arguments[5];

var stringify = JSON.stringify;

module.exports = function (fn) {
    var wkey;
    var cacheKeys = Object.keys(cache);

    for (var i = 0, l = cacheKeys.length; i < l; i++) {
        var key = cacheKeys[i];
        var exp = cache[key].exports;
        // Using babel as a transpiler to use esmodule, the export will always
        // be an object with the default export as a property of it. To ensure
        // the existing api and babel esmodule exports are both supported we
        // check for both
        if (exp === fn || exp.default === fn) {
            wkey = key;
            break;
        }
    }

    if (!wkey) {
        wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
        var wcache = {};
        for (var i = 0, l = cacheKeys.length; i < l; i++) {
            var key = cacheKeys[i];
            wcache[key] = key;
        }
        sources[wkey] = [
            Function(['require','module','exports'], '(' + fn + ')(self)'),
            wcache
        ];
    }
    var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);

    var scache = {}; scache[wkey] = wkey;
    sources[skey] = [
        Function(['require'], (
            // try to call default if defined to also support babel esmodule
            // exports
            'var f = require(' + stringify(wkey) + ');' +
            '(f.default ? f.default : f)(self);'
        )),
        scache
    ];

    var src = '(' + bundleFn + ')({'
        + Object.keys(sources).map(function (key) {
            return stringify(key) + ':['
                + sources[key][0]
                + ',' + stringify(sources[key][1]) + ']'
            ;
        }).join(',')
        + '},{},[' + stringify(skey) + '])'
    ;

    var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

    return new Worker(URL.createObjectURL(
        new Blob([src], { type: 'text/javascript' })
    ));
};
<|endoftext|>


<commit_before><commit_msg>Correct regexp<commit_after><|endoftext|>


<commit_before>'use strict';
var assert = require('assert');
var escapeRegex = require('escape-string-regexp');
var path = require('path');
var slash = require('slash');
var sourceMapUrl = require('source-map-url');

function HtmlWebpackInlineSourcePlugin (options) {
  assert.equal(options, undefined, 'The HtmlWebpackInlineSourcePlugin does not accept any options');
}

HtmlWebpackInlineSourcePlugin.prototype.apply = function (compiler) {
  var self = this;

  // Hook into the html-webpack-plugin processing

  (compiler.hooks
    ? compiler.hooks.compilation.tap.bind(compiler.hooks.compilation, 'html-webpack-inline-source-plugin')
    : compiler.plugin.bind(compiler, 'compilation'))(function (compilation) {
      (compilation.hooks
      ? compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync.bind(compilation.hooks.htmlWebpackPluginAlterAssetTags, 'html-webpack-inline-source-plugin')
      : compilation.plugin.bind(compilation, 'html-webpack-plugin-alter-asset-tags'))(function (htmlPluginData, callback) {
        if (!htmlPluginData.plugin.options.inlineSource) {
          return callback(null, htmlPluginData);
        }

        var regexStr = htmlPluginData.plugin.options.inlineSource;

        var result = self.processTags(compilation, regexStr, htmlPluginData);

        callback(null, result);
      });
    });
};

HtmlWebpackInlineSourcePlugin.prototype.processTags = function (compilation, regexStr, pluginData) {
  var self = this;

  var body = [];
  var head = [];

  var regex = new RegExp(regexStr);
  var filename = pluginData.plugin.options.filename;

  pluginData.head.forEach(function (tag) {
    head.push(self.processTag(compilation, regex, tag, filename));
  });

  pluginData.body.forEach(function (tag) {
    body.push(self.processTag(compilation, regex, tag, filename));
  });

  return { head: head, body: body, plugin: pluginData.plugin, chunks: pluginData.chunks, outputName: pluginData.outputName };
};

HtmlWebpackInlineSourcePlugin.prototype.resolveSourceMaps = function (compilation, assetName, asset) {
  var source = asset.source();
  var out = compilation.outputOptions;
  // Get asset file absolute path
  var assetPath = path.join(out.path, assetName);
  // Extract original sourcemap URL from source string
  if (typeof source !== 'string') {
    source = source.toString();
  }
  var mapUrlOriginal = sourceMapUrl.getFrom(source);
  // Return unmodified source if map is unspecified, URL-encoded, or already relative to site root
  if (!mapUrlOriginal || mapUrlOriginal.indexOf('data:') === 0 || mapUrlOriginal.indexOf('/') === 0) {
    return source;
  }
  // Figure out sourcemap file path *relative to the asset file path*
  var assetDir = path.dirname(assetPath);
  var mapPath = path.join(assetDir, mapUrlOriginal);
  var mapPathRelative = path.relative(out.path, mapPath);
  // Starting with Node 6, `path` module throws on `undefined`
  var publicPath = out.publicPath || '';
  // Prepend Webpack public URL path to source map relative path
  // Calling `slash` converts Windows backslashes to forward slashes
  var mapUrlCorrected = slash(path.join(publicPath, mapPathRelative));
  // Regex: exact original sourcemap URL, possibly '*/' (for CSS), then EOF, ignoring whitespace
  var regex = new RegExp(escapeRegex(mapUrlOriginal) + '(\\s*(?:\\*/)?\\s*$)');
  // Replace sourcemap URL and (if necessary) preserve closing '*/' and whitespace
  return source.replace(regex, function (match, group) {
    return mapUrlCorrected + group;
  });
};

HtmlWebpackInlineSourcePlugin.prototype.processTag = function (compilation, regex, tag, filename) {
  var assetUrl;

  // inline js
  if (tag.tagName === 'script' && tag.attributes && regex.test(tag.attributes.src)) {
    assetUrl = tag.attributes.src;
    tag = {
      tagName: 'script',
      closeTag: true,
      attributes: {
        type: 'text/javascript'
      }
    };

  // inline css
  } else if (tag.tagName === 'link' && regex.test(tag.attributes.href)) {
    assetUrl = tag.attributes.href;
    tag = {
      tagName: 'style',
      closeTag: true,
      attributes: {
        type: 'text/css'
      }
    };
  }

  if (assetUrl) {
    // Strip public URL prefix from asset URL to get Webpack asset name
    var publicUrlPrefix = compilation.outputOptions.publicPath || '';
    // if filename is in subfolder, assetUrl should be prepended folder path
    if (path.basename(filename) !== filename) {
      assetUrl = path.dirname(filename) + '/' + assetUrl;
    }
    var assetName = path.posix.relative(publicUrlPrefix, assetUrl);
    var asset = getAssetByName(compilation.assets, assetName);
    var updatedSource = this.resolveSourceMaps(compilation, assetName, asset);
    tag.innerHTML = (tag.tagName === 'script') ? updatedSource.replace(/(<)(\/script>)/g, '\\x3C$2') : updatedSource;
  }

  return tag;
};

function getAssetByName (assests, assetName) {
  for (var key in assests) {
    if (assests.hasOwnProperty(key)) {
      var processedKey = path.posix.relative('', key);
      if (processedKey === assetName) {
        return assests[key];
      }
    }
  }
}

module.exports = HtmlWebpackInlineSourcePlugin;
<commit_msg>Make plugin compatible with the HTML Webpack Plugin version 4<commit_after>'use strict';
var assert = require('assert');
var escapeRegex = require('escape-string-regexp');
var path = require('path');
var slash = require('slash');
var sourceMapUrl = require('source-map-url');

function HtmlWebpackInlineSourcePlugin (htmlWebpackPlugin, options) {
  this.htmlWebpackPlugin = htmlWebpackPlugin;
  assert.equal(options, undefined, 'The HtmlWebpackInlineSourcePlugin does not accept any options');
}

HtmlWebpackInlineSourcePlugin.prototype.apply = function (compiler) {
  var self = this;

  // Hook into the html-webpack-plugin processing
  compiler.hooks.compilation.tap('html-webpack-inline-source-plugin', compilation => {
    self.htmlWebpackPlugin
      .getHooks(compilation)
      .alterAssetTagGroups.tapAsync('html-webpack-inline-source-plugin', (htmlPluginData, callback) => {
        if (!htmlPluginData.plugin.options.inlineSource) {
          return callback(null, htmlPluginData);
        }

        var regexStr = htmlPluginData.plugin.options.inlineSource;

        var result = self.processTags(compilation, regexStr, htmlPluginData);

        callback(null, result);
      })
  })
};

HtmlWebpackInlineSourcePlugin.prototype.processTags = function (compilation, regexStr, pluginData) {
  var self = this;

  var bodyTags = [];
  var headTags = [];

  var regex = new RegExp(regexStr);

  pluginData.headTags.forEach(function (tag) {
    headTags.push(self.processTag(compilation, regex, tag));
  });

  pluginData.bodyTags.forEach(function (tag) {
    bodyTags.push(self.processTag(compilation, regex, tag));
  });

  return { headTags: headTags, bodyTags: bodyTags, plugin: pluginData.plugin, outputName: pluginData.outputName };
};

HtmlWebpackInlineSourcePlugin.prototype.resolveSourceMaps = function (compilation, assetName, asset) {
  var source = asset.source();
  var out = compilation.outputOptions;
  // Get asset file absolute path
  var assetPath = path.join(out.path, assetName);
  // Extract original sourcemap URL from source string
  if (typeof source !== 'string') {
    source = source.toString();
  }
  var mapUrlOriginal = sourceMapUrl.getFrom(source);
  // Return unmodified source if map is unspecified, URL-encoded, or already relative to site root
  if (!mapUrlOriginal || mapUrlOriginal.indexOf('data:') === 0 || mapUrlOriginal.indexOf('/') === 0) {
    return source;
  }
  // Figure out sourcemap file path *relative to the asset file path*
  var assetDir = path.dirname(assetPath);
  var mapPath = path.join(assetDir, mapUrlOriginal);
  var mapPathRelative = path.relative(out.path, mapPath);
  // Starting with Node 6, `path` module throws on `undefined`
  var publicPath = out.publicPath || '';
  // Prepend Webpack public URL path to source map relative path
  // Calling `slash` converts Windows backslashes to forward slashes
  var mapUrlCorrected = slash(path.join(publicPath, mapPathRelative));
  // Regex: exact original sourcemap URL, possibly '*/' (for CSS), then EOF, ignoring whitespace
  var regex = new RegExp(escapeRegex(mapUrlOriginal) + '(\\s*(?:\\*/)?\\s*$)');
  // Replace sourcemap URL and (if necessary) preserve closing '*/' and whitespace
  return source.replace(regex, function (match, group) {
    return mapUrlCorrected + group;
  });
};

HtmlWebpackInlineSourcePlugin.prototype.processTag = function (compilation, regex, tag) {
  var assetUrl;

  // inline js
  if (tag.tagName === 'script' && regex.test(tag.attributes.src)) {
    assetUrl = tag.attributes.src;
    tag = {
      tagName: 'script',
      closeTag: true,
      attributes: {
        type: 'text/javascript'
      }
    };

  // inline css
  } else if (tag.tagName === 'link' && regex.test(tag.attributes.href)) {
    assetUrl = tag.attributes.href;
    tag = {
      tagName: 'style',
      closeTag: true,
      attributes: {
        type: 'text/css'
      }
    };
  }

  if (assetUrl) {
    // Strip public URL prefix from asset URL to get Webpack asset name
    var publicUrlPrefix = compilation.outputOptions.publicPath || '';
    var assetName = path.posix.relative(publicUrlPrefix, assetUrl);
    var asset = compilation.assets[assetName];
    var updatedSource = this.resolveSourceMaps(compilation, assetName, asset);
    tag.innerHTML = (tag.tagName === 'script') ? updatedSource.replace(/(<)(\/script>)/g, '\\x3C$2') : updatedSource;
  }

  return tag;
};

module.exports = HtmlWebpackInlineSourcePlugin;
<|endoftext|>


<commit_before>var Storage = (function(){
    function Storage() {
        this.initialize.call(this);
    };
    //默认属性
    Storage.prototype = {
        constructor: Storage,
        propertys: function () {
            //代理对象，默认为localstorage
            this.sProxy = window.localStorage;
            //60 * 60 * 24 * 30 * 1000 ms ==30天
            this.defaultLifeTime = 2592000000;
            //本地缓存用以存放所有localstorage键值与过期日期的映射
            this.keyCache = 'SYSTEM_KEY_TIMEOUT_MAP';
            //当缓存容量已满，每次删除的缓存数
            this.removeNum = 5;
        },
        assert: function () {
            if (this.sProxy === null) {
                throw 'not override sProxy property';
            }
        },
        initialize: function (opts) {
            this.propertys();
            this.assert();
        },
        /* 新增localstorage
        数据格式包括唯一键值，json字符串，过期日期，存入日期
        sign 为格式化后的请求参数，用于同一请求不同参数时候返回新数据，比如列表为北京的城市，后切换为上海，会判断tag不同而更新缓存数据，tag相当于签名
        每一键值只会缓存一条信息
        */
        set: function (key, value, timeout, sign) {
            var _d = new Date();
            //存入日期
            var indate = _d.getTime();
            //最终保存的数据
            var entity = null;
            if (!timeout) {
                _d.setTime(_d.getTime() + this.defaultLifeTime);
                timeout = _d.getTime();
            }
            //
            this.setKeyCache(key, timeout);
            entity = this.buildStorageObj(value, indate, timeout, sign);

            try {
                this.sProxy.setItem(key, JSON.stringify(entity));
                return true;
            } catch (e) {
                //localstorage写满时,全清掉
                if (e.name == 'QuotaExceededError') {
                //            this.sProxy.clear();
                //localstorage写满时，选择离过期时间最近的数据删除，这样也会有些影响，但是感觉比全清除好些，如果缓存过多，此过程比较耗时，100ms以内
                if (!this.removeLastCache()) throw '本次数据存储量过大';
                this.set(key, value, timeout, sign);
                }
                console && console.log(e);
            }
            return false;
        },
        //删除过期缓存
        removeOverdueCache: function () {
            var tmpObj = null, i, len;
            var now = new Date().getTime();
            //取出键值对
            var cacheStr = this.sProxy.getItem(this.keyCache);
            var cacheMap = [];
            var newMap = [];
            if (!cacheStr) {
                return;
            }
            cacheMap = JSON.parse(cacheStr);
            for (i = 0, len = cacheMap.length; i < len; i++) {
                tmpObj = cacheMap[i];
                if (tmpObj.timeout < now) {
                    this.sProxy.removeItem(tmpObj.key);
                } else {
                    newMap.push(tmpObj);
                }
            }
            this.sProxy.setItem(this.keyCache, JSON.stringify(newMap));
        },
        removeLastCache: function () {
            var i, len;
            var num = this.removeNum || 5;
            //取出键值对
            var cacheStr = this.sProxy.getItem(this.keyCache);
            var cacheMap = [];
            var delMap = [];

            //说明本次存储过大
            if (!cacheStr) return false;

            cacheMap.sort(function (a, b) {
                return a.timeout - b.timeout;
            });

            //删除了哪些数据
            delMap = cacheMap.splice(0, num);
            for (i = 0, len = delMap.length; i < len; i++) {
                this.sProxy.removeItem(delMap[i].key);
            }
            this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap));
            return true;
        },

        setKeyCache: function (key, timeout) {
            if (!key || !timeout || timeout < new Date().getTime())
                return;
            var i, len, tmpObj;

            //获取当前已经缓存的键值字符串
            var oldstr = this.sProxy.getItem(this.keyCache);
            var oldMap = [];
            //当前key是否已经存在
            var flag = false;
            var obj = {};
            obj.key = key;
            obj.timeout = timeout;

            if (oldstr) {
                oldMap = JSON.parse(oldstr);
                if (!_.isArray(oldMap)) {
                    oldMap = [];
                }
            }
            for (i = 0, len = oldMap.length; i < len; i++) {
                tmpObj = oldMap[i];
                if (tmpObj.key == key) {
                    oldMap[i] = obj;
                    flag = true;
                    break;
                }
            }
            if (!flag) oldMap.push(obj);
            //最后将新数组放到缓存中
            this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));
        },

        buildStorageObj: function (value, indate, timeout, sign) {
            var obj = {
                value: value,
                timeout: timeout,
                sign: sign,
                indate: indate
            };
            return obj;
        },

        get: function (key, sign) {
            var result, now = new Date().getTime();
            try {
                result = this.sProxy.getItem(key);
                if (!result) {
                    return null
                };
                result = JSON.parse(result);

                //数据过期
                console.log(result, now);
                if (result.indate < now) {
                    return null
                };

                //需要验证签名
                if (sign) {
                    if (sign === result.sign) {
                        return result.value;
                    }
                    return null;
                } else {
                    return result.value;
                }
            } catch (e) {
                console && console.log(e);
            }
            return null;
        },

        //获取签名
        getSign: function (key) {
            var result, sign = null;
            try {
                result = this.sProxy.getItem(key);
                if (result) {
                    result = JSON.parse(result);
                    sign = result && result.sign
                }
            } catch (e) {
                console && console.log(e);
            }
            return sign;
        },

        remove: function (key) {
            return this.sProxy.removeItem(key);
        },

        clear: function () {
            this.sProxy.clear();
        }
    };
    return Storage;
}());

Storage.getInstance = function () {
    if (this.instance) {
        return this.instance;
    } else {
        return this.instance = new this();
    }
};

module.exports = Storage.getInstance();
<commit_msg>修复数据过期不删除问题<commit_after>var Storage = (function(){
    function Storage() {
        this.initialize.call(this);
    };
    //默认属性
    Storage.prototype = {
        constructor: Storage,
        propertys: function () {
            //代理对象，默认为localstorage
            this.sProxy = window.localStorage;
            //60 * 60 * 24 * 30 * 1000 ms ==30天
            this.defaultLifeTime = 2592000000;
            //本地缓存用以存放所有localstorage键值与过期日期的映射
            this.keyCache = 'SYSTEM_KEY_TIMEOUT_MAP';
            //当缓存容量已满，每次删除的缓存数
            this.removeNum = 5;
        },
        assert: function () {
            if (this.sProxy === null) {
                throw 'not override sProxy property';
            }
        },
        initialize: function (opts) {
            this.propertys();
            this.assert();
        },
        /* 新增localstorage
        数据格式包括唯一键值，json字符串，过期日期，存入日期
        sign 为格式化后的请求参数，用于同一请求不同参数时候返回新数据，比如列表为北京的城市，后切换为上海，会判断tag不同而更新缓存数据，tag相当于签名
        每一键值只会缓存一条信息
        */
        /**
         * 设置本地缓存
         * @param {[String]} key     [key值]
         * @param {[Object|String]} value   [value值]
         * @param {[String]} timeout [超时时间]
         * @param {[String]} sign    [签名校验]
         */
        set: function (key, value, timeout, sign) {
            var _d = new Date();
            //存入日期
            var indate = _d.getTime();
            this.removeOverdueCache();
            //最终保存的数据
            var entity = null;
            if (!timeout) {
                _d.setTime(_d.getTime() + this.defaultLifeTime);
                timeout = _d.getTime();
            } else {
                timeout = _d.getTime() + timeout;
            }
            this.setKeyCache(key, timeout);
            entity = this.buildStorageObj(value, indate, timeout, sign);

            try {
                this.sProxy.setItem(key, JSON.stringify(entity));
                return true;
            } catch (e) {
                //localstorage写满时,全清掉
                if (e.name == 'QuotaExceededError') {
                //            this.sProxy.clear();
                //localstorage写满时，选择离过期时间最近的数据删除，这样也会有些影响，但是感觉比全清除好些，如果缓存过多，此过程比较耗时，100ms以内
                if (!this.removeLastCache()) throw '本次数据存储量过大';
                this.set(key, value, timeout, sign);
                }
                console && console.log(e);
            }
            return false;
        },
        //删除过期缓存
        removeOverdueCache: function () {
            var tmpObj = null, i, len;
            var now = new Date().getTime();
            //取出键值对
            var cacheStr = this.sProxy.getItem(this.keyCache);
            var cacheMap = [];
            var newMap = [];
            if (!cacheStr) {
                return;
            }
            cacheMap = JSON.parse(cacheStr);
            for (i = 0, len = cacheMap.length; i < len; i++) {
                tmpObj = cacheMap[i] || {};
                if (tmpObj.timeout < now) {
                    this.sProxy.removeItem(tmpObj.key);
                } else {
                    newMap.push(tmpObj);
                }
            }
            this.sProxy.setItem(this.keyCache, JSON.stringify(newMap));
        },
        removeLastCache: function () {
            var i, len;
            var num = this.removeNum || 5;
            //取出键值对
            var cacheStr = this.sProxy.getItem(this.keyCache);
            var cacheMap = [];
            var delMap = [];

            //说明本次存储过大
            if (!cacheStr) return false;

            cacheMap.sort(function (a, b) {
                return a.indate - b.indate;
            });

            //删除了哪些数据
            delMap = cacheMap.splice(0, num);
            for (i = 0, len = delMap.length; i < len; i++) {
                this.sProxy.removeItem(delMap[i].key);
            }
            this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap));
            return true;
        },

        setKeyCache: function (key, timeout) {
            if (!key || !timeout || timeout < new Date().getTime())
                return;
            var i, len, tmpObj;

            //获取当前已经缓存的键值字符串
            var oldstr = this.sProxy.getItem(this.keyCache);
            var oldMap = [];
            //当前key是否已经存在
            var flag = false;
            var obj = {};
            obj.key = key;
            obj.timeout = timeout;

            if (oldstr) {
                oldMap = JSON.parse(oldstr);
                if (Object.prototype.toString.call(oldMap) !== '[object Array]') {
                    oldMap = [];
                }
            }
            for (i = 0, len = oldMap.length; i < len; i++) {
                tmpObj = oldMap[i];
                if (tmpObj.key == key) {
                    oldMap[i] = obj;
                    flag = true;
                    break;
                }
            }
            if (!flag) oldMap.push(obj);
            //最后将新数组放到缓存中
            this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));
        },

        buildStorageObj: function (value, indate, timeout, sign) {
            var obj = {
                value: value,
                timeout: timeout,
                sign: sign,
                indate: indate
            };
            return obj;
        },

        get: function (key, sign) {
            var result, now = new Date().getTime();
            this.removeOverdueCache();
            try {
                result = this.sProxy.getItem(key);
                if (!result) {
                    return null
                };
                result = JSON.parse(result);

                //数据过期
                if (result.timeout < now) {
                    return null
                };

                //需要验证签名
                if (sign) {
                    if (sign === result.sign) {
                        return result.value;
                    }
                    return null;
                } else {
                    return result.value;
                }
            } catch (e) {
                console && console.log(e);
            }
            return null;
        },

        //获取签名
        getSign: function (key) {
            var result, sign = null;
            try {
                result = this.sProxy.getItem(key);
                if (result) {
                    result = JSON.parse(result);
                    sign = result && result.sign
                }
            } catch (e) {
                console && console.log(e);
            }
            return sign;
        },

        remove: function (key) {
            return this.sProxy.removeItem(key);
        },

        clear: function () {
            this.sProxy.clear();
        }
    };
    return Storage;
}());

Storage.getInstance = function () {
    if (this.instance) {
        return this.instance;
    } else {
        return this.instance = new this();
    }
};

module.exports = Storage.getInstance();
<|endoftext|>


<commit_before>// Get forum topics created by a user
//
// In:
//
// - params.user_id
// - params.user_info
// - params.start - starting point (topic id, optional, default: most recent one)
// - params.before - number of visible topics fetched before start
// - params.after - number of visible topics fetched after start
//
// Out:
//
// - results - array of results, each one is { topic, section }
// - users - array of user ids needed to fetch
// - reached_top
// - reached_bottom
//

'use strict';

const _                = require('lodash');
const sanitize_topic   = require('nodeca.forum/lib/sanitizers/topic');
const sanitize_section = require('nodeca.forum/lib/sanitizers/section');

module.exports = function (N, apiPath) {

  // Separate method used to return number of items
  //
  N.wire.on(apiPath + ':count', async function activity_forum_topics_count(locals) {
    locals.count = await N.models.forum.UserTopicCount.get(locals.params.user_id, locals.params.user_info);
  });

  // Initialize internal state
  //
  N.wire.before(apiPath, { priority: -20 }, async function init_activity_env(locals) {
    locals.sandbox = {};

    // get visible sections
    locals.sandbox.visible_sections = await N.models.forum.Section.getVisibleSections(
      locals.params.user_info.usergroups
    );

    // get visible statuses
    locals.sandbox.countable_statuses = N.models.forum.Topic.statuses.LIST_VISIBLE.slice(0);

    // NOTE: do not count deleted topics, since permissions may be different
    //       for different sections, depending on usergroup and moderator
    //       permissions; deleted topics will be checked and filtered out later
    if (locals.params.user_info.hb) locals.sandbox.countable_statuses.push(N.models.forum.Topic.statuses.HB);
  });

  // Find first visible topic
  //
  N.wire.before(apiPath, { parallel: true }, async function find_topic_range_before(locals) {
    if (!locals.params.before) {
      locals.sandbox.first_id = locals.params.start;
      return;
    }

    let query = N.models.forum.Topic.findOne()
                               .where('cache.last_user').equals(locals.params.user_id)
                               .where('section').in(locals.sandbox.visible_sections)
                               .where('st').in(locals.sandbox.countable_statuses)
                               .skip(locals.params.before)
                               .sort('_id')
                               .select('_id');

    if (locals.params.start) {
      query = query.where('_id').gt(locals.params.start);
    }

    let first_topic = await query.lean(true);

    if (!first_topic) {
      locals.sandbox.first_id = null;
      return;
    }

    locals.sandbox.first_id = String(first_topic._id);
  });

  // Find last visible topic
  //
  N.wire.before(apiPath, { parallel: true }, async function find_topic_range_after(locals) {
    if (!locals.params.after) {
      locals.sandbox.last_id = locals.params.start;
      return;
    }

    let query = N.models.forum.Topic.findOne()
                               .where('cache.last_user').equals(locals.params.user_id)
                               .where('section').in(locals.sandbox.visible_sections)
                               .where('st').in(locals.sandbox.countable_statuses)
                               .skip(locals.params.after)
                               .sort('-_id')
                               .select('_id');

    if (locals.params.start) {
      query = query.where('_id').lt(locals.params.start);
    }

    let last_topic = await query.lean(true);

    if (!last_topic) {
      locals.sandbox.last_id = null;
      return;
    }

    locals.sandbox.last_id = String(last_topic._id);
  });

  // Find topics
  //
  N.wire.on(apiPath, async function find_topics(locals) {
    let query = N.models.forum.Topic.find()
                    .where('cache.first_user').equals(locals.params.user_id)
                    .where('section').in(locals.sandbox.visible_sections)
                    .sort('-_id');

    if (locals.params.before) {
      query = locals.sandbox.first_id ? query.where('_id').lt(locals.sandbox.first_id) : query;
    } else {
      query = locals.params.start ? query.where('_id').lte(locals.params.start) : query;
    }

    if (locals.params.after) {
      query = locals.sandbox.last_id ? query.where('_id').gt(locals.sandbox.last_id) : query;
    } else {
      query = locals.params.start ? query.where('_id').gte(locals.params.start) : query;
    }

    locals.sandbox.topics = await query.lean(true);

    locals.sandbox.sections = await N.models.forum.Section.find()
                                        .where('_id')
                                        .in(_.uniq(locals.sandbox.topics.map(topic => String(topic.section))))
                                        .lean(true);

    locals.reached_top    = !locals.sandbox.first_id;
    locals.reached_bottom = !locals.sandbox.last_id;
  });

  // Check permissions for each topic
  //
  N.wire.on(apiPath, async function check_permissions(locals) {
    if (!locals.sandbox.topics.length) return;

    let access_env = { params: {
      topics: locals.sandbox.topics,
      user_info: locals.params.user_info,
      preload: locals.sandbox.sections
    } };

    await N.wire.emit('internal:forum.access.topic', access_env);

    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');
    let sections_used = {};

    locals.sandbox.topics = locals.sandbox.topics.filter((topic, idx) => {
      let section = sections_by_id[topic.section];
      if (!section) return false;

      if (access_env.data.access_read[idx]) {
        sections_used[section._id] = section;
        return true;
      }

      return false;
    });

    locals.sandbox.sections = Object.values(sections_used);
  });

  // Sanitize results
  //
  N.wire.on(apiPath, async function sanitize(locals) {
    if (!locals.sandbox.topics.length) return;

    locals.sandbox.topics   = await sanitize_topic(N, locals.sandbox.topics, locals.params.user_info);
    locals.sandbox.sections = await sanitize_section(N, locals.sandbox.sections, locals.params.user_info);
  });

  // Fill results
  //
  N.wire.on(apiPath, function fill_results(locals) {
    locals.results = [];

    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    locals.sandbox.topics.forEach(topic => {
      let section = sections_by_id[topic.section];
      if (!section) return;

      locals.results.push({ topic, section });
    });
  });

  // Fill users
  //
  N.wire.on(apiPath, function fill_users(locals) {
    let users = {};

    locals.results.forEach(result => {
      let topic = result.topic;

      if (topic.cache.first_user) users[topic.cache.first_user] = true;
      if (topic.cache.last_user) users[topic.cache.last_user] = true;
      if (topic.del_by) users[topic.del_by] = true;
    });

    locals.users = Object.keys(users);
  });
};
<commit_msg>Fix preload freeze in activity<commit_after>// Get forum topics created by a user
//
// In:
//
// - params.user_id
// - params.user_info
// - params.start - starting point (topic id, optional, default: most recent one)
// - params.before - number of visible topics fetched before start
// - params.after - number of visible topics fetched after start
//
// Out:
//
// - results - array of results, each one is { topic, section }
// - users - array of user ids needed to fetch
// - reached_top
// - reached_bottom
//

'use strict';

const _                = require('lodash');
const sanitize_topic   = require('nodeca.forum/lib/sanitizers/topic');
const sanitize_section = require('nodeca.forum/lib/sanitizers/section');

module.exports = function (N, apiPath) {

  // Separate method used to return number of items
  //
  N.wire.on(apiPath + ':count', async function activity_forum_topics_count(locals) {
    locals.count = await N.models.forum.UserTopicCount.get(locals.params.user_id, locals.params.user_info);
  });

  // Initialize internal state
  //
  N.wire.before(apiPath, { priority: -20 }, async function init_activity_env(locals) {
    locals.sandbox = {};

    // get visible sections
    locals.sandbox.visible_sections = await N.models.forum.Section.getVisibleSections(
      locals.params.user_info.usergroups
    );

    // get visible statuses
    locals.sandbox.countable_statuses = N.models.forum.Topic.statuses.LIST_VISIBLE.slice(0);

    // NOTE: do not count deleted topics, since permissions may be different
    //       for different sections, depending on usergroup and moderator
    //       permissions; deleted topics will be checked and filtered out later
    if (locals.params.user_info.hb) locals.sandbox.countable_statuses.push(N.models.forum.Topic.statuses.HB);
  });

  // Find first visible topic
  //
  N.wire.before(apiPath, { parallel: true }, async function find_topic_range_before(locals) {
    if (!locals.params.before) {
      locals.sandbox.first_id = locals.params.start;
      return;
    }

    let query = N.models.forum.Topic.findOne()
                               .where('cache.first_user').equals(locals.params.user_id)
                               .where('section').in(locals.sandbox.visible_sections)
                               .where('st').in(locals.sandbox.countable_statuses)
                               .skip(locals.params.before)
                               .sort('_id')
                               .select('_id');

    if (locals.params.start) {
      query = query.where('_id').gt(locals.params.start);
    }

    let first_topic = await query.lean(true);

    if (!first_topic) {
      locals.sandbox.first_id = null;
      return;
    }

    locals.sandbox.first_id = String(first_topic._id);
  });

  // Find last visible topic
  //
  N.wire.before(apiPath, { parallel: true }, async function find_topic_range_after(locals) {
    if (!locals.params.after) {
      locals.sandbox.last_id = locals.params.start;
      return;
    }

    let query = N.models.forum.Topic.findOne()
                               .where('cache.first_user').equals(locals.params.user_id)
                               .where('section').in(locals.sandbox.visible_sections)
                               .where('st').in(locals.sandbox.countable_statuses)
                               .skip(locals.params.after)
                               .sort('-_id')
                               .select('_id');

    if (locals.params.start) {
      query = query.where('_id').lt(locals.params.start);
    }

    let last_topic = await query.lean(true);

    if (!last_topic) {
      locals.sandbox.last_id = null;
      return;
    }

    locals.sandbox.last_id = String(last_topic._id);
  });

  // Find topics
  //
  N.wire.on(apiPath, async function find_topics(locals) {
    let query = N.models.forum.Topic.find()
                    .where('cache.first_user').equals(locals.params.user_id)
                    .where('section').in(locals.sandbox.visible_sections)
                    .sort('-_id');

    if (locals.params.before) {
      query = locals.sandbox.first_id ? query.where('_id').lt(locals.sandbox.first_id) : query;
    } else {
      query = locals.params.start ? query.where('_id').lte(locals.params.start) : query;
    }

    if (locals.params.after) {
      query = locals.sandbox.last_id ? query.where('_id').gt(locals.sandbox.last_id) : query;
    } else {
      query = locals.params.start ? query.where('_id').gte(locals.params.start) : query;
    }

    locals.sandbox.topics = await query.lean(true);

    locals.sandbox.sections = await N.models.forum.Section.find()
                                        .where('_id')
                                        .in(_.uniq(locals.sandbox.topics.map(topic => String(topic.section))))
                                        .lean(true);

    locals.reached_top    = !locals.sandbox.first_id;
    locals.reached_bottom = !locals.sandbox.last_id;
  });

  // Check permissions for each topic
  //
  N.wire.on(apiPath, async function check_permissions(locals) {
    if (!locals.sandbox.topics.length) return;

    let access_env = { params: {
      topics: locals.sandbox.topics,
      user_info: locals.params.user_info,
      preload: locals.sandbox.sections
    } };

    await N.wire.emit('internal:forum.access.topic', access_env);

    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');
    let sections_used = {};

    locals.sandbox.topics = locals.sandbox.topics.filter((topic, idx) => {
      let section = sections_by_id[topic.section];
      if (!section) return false;

      if (access_env.data.access_read[idx]) {
        sections_used[section._id] = section;
        return true;
      }

      return false;
    });

    locals.sandbox.sections = Object.values(sections_used);
  });

  // Sanitize results
  //
  N.wire.on(apiPath, async function sanitize(locals) {
    if (!locals.sandbox.topics.length) return;

    locals.sandbox.topics   = await sanitize_topic(N, locals.sandbox.topics, locals.params.user_info);
    locals.sandbox.sections = await sanitize_section(N, locals.sandbox.sections, locals.params.user_info);
  });

  // Fill results
  //
  N.wire.on(apiPath, function fill_results(locals) {
    locals.results = [];

    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    locals.sandbox.topics.forEach(topic => {
      let section = sections_by_id[topic.section];
      if (!section) return;

      locals.results.push({ topic, section });
    });
  });

  // Fill users
  //
  N.wire.on(apiPath, function fill_users(locals) {
    let users = {};

    locals.results.forEach(result => {
      let topic = result.topic;

      if (topic.cache.first_user) users[topic.cache.first_user] = true;
      if (topic.cache.last_user) users[topic.cache.last_user] = true;
      if (topic.del_by) users[topic.del_by] = true;
    });

    locals.users = Object.keys(users);
  });
};
<|endoftext|>


<commit_before>'use strict';

var Base = require('base');
var util = require('expand-utils');
var utils = require('./utils');

/**
 * Create a new Target with the given `options`
 *
 * ```js
 * var target = new Target();
 * target.expand({src: '*.js', dest: 'foo/'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Target(options) {
  if (!(this instanceof Target)) {
    return new Target(options);
  }

  Base.call(this, {}, options);
  this.use(utils.plugins());
  this.is('Target');

  this.options = options || {};
  this.define('Expand', this.options.expand || utils.Expand);

  if (util.isTarget(options)) {
    this.options = {};
    this.addFiles(options);
    return this;
  }
}

/**
 * Inherit `Base`
 */

Base.extend(Target);

/**
 * Expand src-dest mappings and glob patterns in the given `files` configuration.
 *
 * ```js
 * target.addFiles({
 *   'a/': ['*.js'],
 *   'b/': ['*.js'],
 *   'c/': ['*.js']
 * });
 * ```
 * @param {Object} `files`
 * @return {Object} Instance of `Target` for chaining.
 * @api public
 */

Target.prototype.addFiles = function(files) {
  var config = new this.Expand(this.options);
  config.on('files', this.emit.bind(this, 'files'));

  // run plugins on `config`
  util.run(this, 'target', config);
  config.expand(files);

  for (var key in config) {
    if (config.hasOwnProperty(key) && !(key in this)) {
      this[key] = config[key];
    }
  }
  return this;
};

/**
 * Expose `Target`
 */

module.exports = Target;
<commit_msg>emit `files` on the ctor<commit_after>'use strict';

var Base = require('base');
var util = require('expand-utils');
var utils = require('./utils');

/**
 * Create a new Target with the given `options`
 *
 * ```js
 * var target = new Target();
 * target.expand({src: '*.js', dest: 'foo/'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Target(options) {
  if (!(this instanceof Target)) {
    return new Target(options);
  }

  Base.call(this, {}, options);
  this.use(utils.plugins());
  this.is('Target');

  this.options = options || {};
  this.define('Expand', this.options.expand || utils.Expand);
  this.on('files', Target.emit.bind(Target, 'files'));

  if (util.isTarget(options)) {
    this.options = {};
    this.addFiles(options);
    return this;
  }
}

/**
 * Inherit `Base`
 */

Base.extend(Target);

/**
 * Expand src-dest mappings and glob patterns in the given `files` configuration.
 *
 * ```js
 * target.addFiles({
 *   'a/': ['*.js'],
 *   'b/': ['*.js'],
 *   'c/': ['*.js']
 * });
 * ```
 * @param {Object} `files`
 * @return {Object} Instance of `Target` for chaining.
 * @api public
 */

Target.prototype.addFiles = function(files) {
  var config = new this.Expand(this.options);
  config.on('files', this.emit.bind(this, 'files'));

  // run plugins on `config`
  util.run(this, 'target', config);
  config.expand(files);

  for (var key in config) {
    if (config.hasOwnProperty(key) && !(key in this)) {
      this[key] = config[key];
    }
  }
  return this;
};

/**
 * Expose `Target`
 */

module.exports = Target;
<|endoftext|>


<commit_before>import {extent, mean} from "d3-array";
import {titleCase} from "d3plus-text";

import {COLORS_RAINFALL} from "helpers/colors";
import {DICTIONARY} from "helpers/dictionary";
import {VARIABLES} from "helpers/formatters";

const axisConfig = {
  barConfig: {
    "stroke": "#dddddd",
    "stroke-width": 1
  },
  gridConfig: {
    "stroke": "#dddddd",
    "stroke-width": 1
  },
  shapeConfig: {
    fill: "#979797",
    labelConfig: {
      fontColor: "rgba(0, 0, 0, 0.8)",
      fontFamily: () => "Work Sans",
      fontSize: () => 12
    },
    stroke: "#979797"
  },
  tickSize: 0,
  titleConfig: {
    fontFamily: () => "Work Sans",
    fontSize: "14px",
    fontWeight: 600,
    textTransform: "uppercase"
  }
};

export default {
  aggs: {
    poverty_prop: mean,
    proportion_of_children: mean,
    year: arr => {
      const e = extent(arr);
      return e[0] === e[1] ? e[0] : e.join("–");
    }
  },
  barPadding: 4,
  cache: true,
  colorScaleConfig: {
    color: COLORS_RAINFALL,
    scale: "jenks",
    shapeConfig: {
      fill: "#979797",
      labelConfig: {
        fontColor: "rgba(0, 0, 0, 0.8)",
        fontFamily: () => "Work Sans",
        fontSize: () => 12
      },
      stroke: "#979797"
    },
    tickSize: 0,
    titleConfig: {
      fontFamily: () => "Work Sans",
      fontSize: "14px",
      fontWeight: 600,
      textTransform: "uppercase"
    }
  },
  controlConfig: {
    buttonStyle: {
      margin: "12px"
    },
    labelStyle: {
      "color": "rgba(0, 0, 0, 0.2)",
      "display": "inline-block",
      "font-family": "Work Sans",
      "font-size": "12px",
      "font-weight": 600,
      "padding": "12px 16px"
    }
  },
  downloadButton: true,
  legendConfig: {
    marginLeft: 50,
    padding: 8,
    shapeConfig: {
      labelConfig: {
        fontColor: "rgba(0, 0, 0, 0.8)",
        fontFamily: () => "Work Sans",
        fontResize: false,
        fontSize: 12,
        fontWeight: 400
      },
      height: () => 20,
      width: () => 20
    },
    tooltipConfig: {
      body: false
    }
  },
  shapeConfig: {
    hoverOpacity: 0.7,
    labelConfig: {
      fontColor: "rgba(0, 0, 0, 0.4)",
      fontFamily: () => "Work Sans",
      fontWeight: 600
    }
  },
  timeline: false,
  titleConfig: {
    fontColor: "#4A4A4A",
    fontFamily: () => "Work Sans"
  },
  tooltipConfig: {
    background: "#fff",
    bodyStyle: {
      "color": "#4A4A4A",
      "font-family": "Work Sans",
      "font-size": "12px",
      "font-weight": 400,
      "margin-top": "12px"
    },
    borderRadius: "4px",
    padding: "16px",
    footer: "click to highlight",
    footerStyle: {
      "color": "#ccc",
      "font-family": "Work Sans",
      "font-size": "12px",
      "margin-top": "10px"
    },
    titleStyle: {
      "color": "#4A4A4A",
      "font-family": "Work Sans",
      "font-size": "16px",
      "font-weight": 600
    }
  },
  xConfig: axisConfig,
  x2Config: {barConfig: axisConfig.barConfig},
  yConfig: axisConfig,
  y2Config: {barConfig: axisConfig.barConfig}
};

export function yearControls(data) {

  const years = Array.from(new Set(data.map(d => d.year))).sort();
  if (years.length < 2) return [];

  function change(year) {
    this.timeFilter(d => d.year === parseFloat(year)).render();
  }

  return [{
    checked: Math.max(...years),
    on: {change},
    options: years.map(year => ({text: year, value: year})),
    type: "Radio"
  }];

}

export function tooltipBody(d) {
  return this.map(key => `<span class="d3plus-body-key">${key in DICTIONARY ? DICTIONARY[key] : titleCase(key)}:</span> <span class="d3plus-body-value">${ key in VARIABLES ? VARIABLES[key](d[key]) : d[key] }</span>`).join("
");
}
<commit_msg>removes click to highlight (closes #107)<commit_after>import {extent, mean} from "d3-array";
import {titleCase} from "d3plus-text";

import {COLORS_RAINFALL} from "helpers/colors";
import {DICTIONARY} from "helpers/dictionary";
import {VARIABLES} from "helpers/formatters";

const axisConfig = {
  barConfig: {
    "stroke": "#dddddd",
    "stroke-width": 1
  },
  gridConfig: {
    "stroke": "#dddddd",
    "stroke-width": 1
  },
  shapeConfig: {
    fill: "#979797",
    labelConfig: {
      fontColor: "rgba(0, 0, 0, 0.8)",
      fontFamily: () => "Work Sans",
      fontSize: () => 12
    },
    stroke: "#979797"
  },
  tickSize: 0,
  titleConfig: {
    fontFamily: () => "Work Sans",
    fontSize: "14px",
    fontWeight: 600,
    textTransform: "uppercase"
  }
};

export default {
  aggs: {
    poverty_prop: mean,
    proportion_of_children: mean,
    year: arr => {
      const e = extent(arr);
      return e[0] === e[1] ? e[0] : e.join("–");
    }
  },
  barPadding: 4,
  cache: true,
  colorScaleConfig: {
    color: COLORS_RAINFALL,
    scale: "jenks",
    shapeConfig: {
      fill: "#979797",
      labelConfig: {
        fontColor: "rgba(0, 0, 0, 0.8)",
        fontFamily: () => "Work Sans",
        fontSize: () => 12
      },
      stroke: "#979797"
    },
    tickSize: 0,
    titleConfig: {
      fontFamily: () => "Work Sans",
      fontSize: "14px",
      fontWeight: 600,
      textTransform: "uppercase"
    }
  },
  controlConfig: {
    buttonStyle: {
      margin: "12px"
    },
    labelStyle: {
      "color": "rgba(0, 0, 0, 0.2)",
      "display": "inline-block",
      "font-family": "Work Sans",
      "font-size": "12px",
      "font-weight": 600,
      "padding": "12px 16px"
    }
  },
  downloadButton: true,
  legendConfig: {
    marginLeft: 50,
    padding: 8,
    shapeConfig: {
      labelConfig: {
        fontColor: "rgba(0, 0, 0, 0.8)",
        fontFamily: () => "Work Sans",
        fontResize: false,
        fontSize: 12,
        fontWeight: 400
      },
      height: () => 20,
      width: () => 20
    },
    tooltipConfig: {
      body: false
    }
  },
  shapeConfig: {
    hoverOpacity: 0.7,
    labelConfig: {
      fontColor: "rgba(0, 0, 0, 0.4)",
      fontFamily: () => "Work Sans",
      fontWeight: 600
    }
  },
  timeline: false,
  titleConfig: {
    fontColor: "#4A4A4A",
    fontFamily: () => "Work Sans"
  },
  tooltipConfig: {
    background: "#fff",
    bodyStyle: {
      "color": "#4A4A4A",
      "font-family": "Work Sans",
      "font-size": "12px",
      "font-weight": 400,
      "margin-top": "12px"
    },
    borderRadius: "4px",
    padding: "16px",
    footerStyle: {
      "color": "#ccc",
      "font-family": "Work Sans",
      "font-size": "12px",
      "margin-top": "10px"
    },
    titleStyle: {
      "color": "#4A4A4A",
      "font-family": "Work Sans",
      "font-size": "16px",
      "font-weight": 600
    }
  },
  xConfig: axisConfig,
  x2Config: {barConfig: axisConfig.barConfig},
  yConfig: axisConfig,
  y2Config: {barConfig: axisConfig.barConfig}
};

export function yearControls(data) {

  const years = Array.from(new Set(data.map(d => d.year))).sort();
  if (years.length < 2) return [];

  function change(year) {
    this.timeFilter(d => d.year === parseFloat(year)).render();
  }

  return [{
    checked: Math.max(...years),
    on: {change},
    options: years.map(year => ({text: year, value: year})),
    type: "Radio"
  }];

}

export function tooltipBody(d) {
  return this.map(key => `<span class="d3plus-body-key">${key in DICTIONARY ? DICTIONARY[key] : titleCase(key)}:</span> <span class="d3plus-body-value">${ key in VARIABLES ? VARIABLES[key](d[key]) : d[key] }</span>`).join("
");
}
<|endoftext|>


<commit_before>/** @jsx dom */
import dom from 'magic-virtual-element';
import scrollTo from 'scroll-to';

const defaultProps = {
	duration: 500,
	ease: 'out-circ',
	top: 0
};

const propTypes = {
	class: {
		type: 'string'
	},
	duration: {
		type: 'number'
	},
	ease: {
		type: 'string'
	},
	show: {
		type: 'number'
	},
	top: {
		type: 'number'
	}
};

function initialState() {
	return {
		active: false
	};
}

function shouldUpdate({state}, nextProps, {active}) {
	return !state.active === active;
}

function afterMount({props}, el, setState) {
	const {show} = props;

	window.addEventListener('scroll', () => {
		if (window.scrollY >= show) {
			setState({active: true});
			return;
		}

		setState({active: false});
	});
}

function render({props, state}) {
	const {children, duration, ease, top} = props;
	const {active} = state;

	return (

 scrollTo(0, top, {ease, duration})}>
			{children}

	);
}

export default {afterMount, defaultProps, initialState, propTypes, render, shouldUpdate};
<commit_msg>Deobfuscate<commit_after>/** @jsx dom */
import dom from 'magic-virtual-element';
import scrollTo from 'scroll-to';

const defaultProps = {
	duration: 500,
	ease: 'out-circ',
	top: 0
};

const propTypes = {
	class: {
		type: 'string'
	},
	duration: {
		type: 'number'
	},
	ease: {
		type: 'string'
	},
	show: {
		type: 'number'
	},
	top: {
		type: 'number'
	}
};

function shouldUpdate({state}, nextProps, {active}) {
	return !state.active === active;
}

function afterMount({props}, el, setState) {
	const {show} = props;

	window.addEventListener('scroll', () => {
		if (window.scrollY >= show) {
			setState({active: true});
			return;
		}

		setState({active: false});
	});
}

function render({props, state}) {
	const {children, duration, ease, top} = props;
	const {active} = state;

	return (

 scrollTo(0, top, {ease, duration})}>
			{children}

	);
}

export default {afterMount, defaultProps, propTypes, render, shouldUpdate};
<|endoftext|>


<commit_before>'use strict';

const repl = require('repl');
const io = require('socket.io');

let randInt = (min, max) => Math.floor(Math.random() * (max - min)) + min;
let randChoose = choices => choices[randInt(0, choices.length)];
class Player {
  constructor(server, id) {
    let config = server.config;
    this.id = id;
    this.clan = null;
    this.server = server;
    this.untilSend = 1;

    this.lastPing = new Date('2017-07-09 5:57:00').getTime();

    this.name = 'unknown';
    this.skin = 0;
    this.size = config.playerScale;
    this.viewedObjects = [];

    this.aimAngle = 0;
    this.movement = null;
    this.kill();
  }
  updateMovement(delta) {
    let config = this.server.config;
    let tx = 0;
    let ty = 0;
    if (this.movement != null) {
      tx = Math.cos(this.movement);
      ty = Math.sin(this.movement);
    }
    this.peek();
    this.vx *= Math.pow(config.playerDecel, delta);
    this.vy *= Math.pow(config.playerDecel, delta);
    this.vx += tx * config.playerSpeed * delta * this.size / 2;
    this.vy += ty * config.playerSpeed * delta * this.size / 2;
    this.x += this.vx;
    this.y += this.vy;
  }
  update(delta) {
    if (this.alive) {
      this.updateMovement(delta);
      this.untilSend--;
      if (!this.untilSend) {
        this.untilSend = this.server.config.clientSendRate;
        this.sendPosition();
      }
    }
  }
  peek() {
    let old = this.viewedObjects;
    let view = this.server.viewObjects(this.x, this.y);
    let sending = [];
    for (let i of view) {
      if (old[i.id]) continue;
      old[i.id] = true;
      sending.push(...i.data);
    }
    if (sending.length) {
      console.log(2)
      this.socket.emit('6', sending)
    }
  }
  sendPosition() {
    let socket = this.socket;
    socket.emit('a');
    socket.emit('3', [
      this.id,
      this.x,
      this.y, -2.26,-1,0,0,null,0,0,0,0]);
  }
  link(socket) {
    let config = this.server.config;
    this.socket = socket;
    socket.once('error', err => {
      console.log(err);
      this.destroy();
    });

    let emitAll = (...arg) => {
      try {
        socket.broadcast.emit(...arg)
        socket.emit(...arg)
      } catch (e) {
      }
    }

    socket.on('2', angle => this.aimAngle = angle);
    socket.on('3', angle => this.movement = angle);

    socket.on('14', data => {
      let now = Date.now();
      let dif = now - this.lastPing;
      if (dif > config.mapPingTime) {
        this.lastPing = now;
        emitAll('p', this.x, this.y);
      }
    });

    socket.on('ch', msg => emitAll('ch', this.id, msg));
    socket.once('disconnect', () => this.destroy());
    socket.emit('id', {
      teams: this.server.clans
    });
    socket.on('1', data => {
      this.name = data.name.length > 15 || !data.name ? 'unknown' : data.name;
      this.skin = data.skin;
      this.spawn();
      this.peek();
    });
  }
  destroy() {
    this.kill();
    this.server.remove(this.id);
    this.socket.disconnect();
  }
  kill() {
    this.alive = false;
    this.x = 0;
    this.y = 0;
    this.slowDown();
  }
  slowDown() {
    this.vx = 0;
    this.vy = 0;
  }
  spawn() {
    let config = this.server.config;
    let socket = this.socket;
    this.alive = true;
    let { x, y } = this.server.allocatePosition(this.size);
    this.x = x;
    this.y = y;
    this.slowDown();
    socket.emit('1', this.id);
    socket.emit('2', [socket.id,this.id,this.name,this.x,this.y,0,100,100,this.size,this.skin],true);
  }
  hitResource(type) {

  }
}
class Resource {
  constructor(server, id, x, y, size, type) {
    let config = server.config;
    this.x = x;
    this.y = y;
    this.id = id;
    this.type = config.resourceTypes.indexOf(type);
    this.size = size;
    this.init();
  }
  reward(by) {
    by.hitResource(this.type);
  }
  init() {
    this.data = [
      this.id,
      this.x,
      this.y,
      0,
      this.size,
      this.type,
      null,
      -1,
    ];
  }
}
class Server {
  constructor(config) {
    this.config = config;
    this.players = Array(config.maxPlayers).fill(null);
    this.lastRun = Date.now();
    this.clans = [];
    this.objects = [];
    setInterval(() => this.update(), config.serverUpdateRate);
    this.generateWorld();
  }
  remove(sid) {
    this.players[sid] = null;
  }
  update() {
    let now = Date.now();
    let delta = now - this.lastRun;
    this.lastRun = now;
    for (let i of this.players) {
      if (i != null) {
        i.update(delta);
      }
    }
  }
  viewObjects(x, y) {
    let config = this.config;
    let visibles = [];
    let width = config.maxScreenWidth;
    let height = config.maxScreenHeight;
    for (let i of this.objects)
      if (
        i.y + height > y &&
        i.y - height < y &&
        i.x + width > x &&
        i.x - width < x
      ) visibles.push(i);
    return visibles;
  }
  viewPlayers(x, y) {
    let config = this.config;
    let visibles = [];
    let width = config.maxScreenWidth;
    let height = config.maxScreenHeight;
    for (let i of this.players)
      if (
        i.y + height > y &&
        i.y - height < y &&
        i.x + width > x &&
        i.x - width < x
      ) visibles.push(i);
    return visibles;
  }
  generateWorld() {
    let config = this.config;
    let areaCount = config.areaCount;
    let mapScale = config.mapScale;
    let riverWidth = config.riverWidth;
    let areaSize = mapScale / areaCount;
    let all = [];
    let id = 0;
    for (let afx = 0, atx = 1; afx < areaCount; afx++, atx++) {
      for (let afy = 0, aty = 1; afy < areaCount; afy++, aty++) {
        for (let i = 0; i < config.treesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          if (y < mapScale - config.snowBiomeTop && (
              y > (mapScale + riverWidth) / 2 ||
              y < (mapScale - riverWidth) / 2)
            ) all.push(new Resource(this, id++, x, y, randChoose(config.treeScales), 'wood'));
        }
        for (let i = 0; i < config.bushesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          if (y > (mapScale + riverWidth) / 2 ||
              y < (mapScale - riverWidth) / 2
            ) all.push(new Resource(this, id++, x, y, randChoose(config.bushScales), 'food'));
        }
      }
    }
    for (let i = 0; i < config.totalRocks; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, id++, x, y, randChoose(config.rockScales), 'stone'));
    }
    for (let i = 0; i < config.goldOres; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      if (y > (mapScale + riverWidth) / 2 ||
          y < (mapScale - riverWidth) / 2
      ) {
        i--;
        continue;
      }
      all.push(new Resource(this, id++, x, y, 50, 'points'));
    }
    this.objects = all;
  }
  allocatePosition(size) {
    let scale = this.config.mapScale;
    let x = 0;
    let y = 0;
    while (true) {
      x = randInt(0, scale);
      y = randInt(0, scale);
      if (true) { // check if there's nothing overlapping
        break;
      }
    }
    return { x, y };
  }
  handle(socket) {
    for (let i = 0; i < this.players.length; i++) {
      if (this.players[i] == null) {
        let player = new Player(this, i);
        player.link(socket);
        this.players[i] = player;
        break;
      }
    }
  }
}

let app = new Server({
  mapScale: 14400,
  maxPlayers: 50,
  clientSendRate: 5,
  serverUpdateRate: 9,
  playerDecel: 0.993,
  playerSpeed: 0.0016,
  playerScale: 35,
  areaCount: 7,
  treesPerArea: 9,
  bushesPerArea: 3,
  totalRocks: 32,
  goldOres: 7,
  resourceTypes: ['wood', 'food', 'stone', 'points'],
  treeScales: [140, 145, 150, 155],
  bushScales: [80, 85, 95],
  rockScales: [80, 85, 90],
  maxScreenWidth: 1920,
  maxScreenHeight: 1080,
  snowBiomeTop: 2400,
  riverWidth: 724,
  mapPingTime: 2200,
});

for (let i = 5000; i <= 5010; i++) {
  io(i).on('connection', socket => app.handle(socket));
}
/*
let teams = [];
let sockets = [];
  io(i).on('connection', function (socket) {
    let emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg);
        socket.emit(...arg);
      } catch (e) {
        sockets.forEach(a => a.emit(...arg));
      }
    };
    sockets.push(socket);
    socket.on('1', function (data) {
      let id = 27;
      let name = data.name.length > 15 ? 'unknown' : data.name;
      socket.emit('id', {
        'teams': teams
      });
      socket.emit('1', id);
      socket.emit('mm', 0);
      socket.emit('3', []);
      let x = randInt(0, config.mapScale);
      let y = randInt(0, config.mapScale);
      let userteam = null;
      let last = 0;
      socket.emit('2', ['a3Pm5dMzeKOjc5gvAJEF', id, name, x, 7200, 0, 100, 100, 35, data.skin], true);
      socket.emit('5', [27, data.name, 9001]); //[5,'RIP',31988,45,'KADEJO503',23404,34,'winter wolf',4821,28,'Godenot',4500,33,'Arena Closer',3000,32,'LightTheif',2940,6,'CarlosKoS-_-16',2800,4,'GD desconhecido',2635,35,'jack black GD',2357,19,'AMIGO BOM',1623])
      socket.emit('6', [
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353, 4103, 13436, 0, 80, 2, null, -1,
        339, 2498, 14155, 0, 90, 2, null, -1
      ]);
      socket.emit('8', 2.6, 28);
      socket.on('ch', data => {
        emit('ch', id, data);
      });
      socket.on('8', data => {
        console.log('CLAN CREATE REQUEST:', data);
        teams.push([{
          'sid': data,
          'owner': id
        }]);
        let userteam = data;
        emit('st', data, true);
      });
      socket.on('3', function (data) {
        if (data == null) {
          vx = vy = 0;
          return;
        } else if (x < 0 || x > config.mapScale || y < 0 || y > config.mapScale) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;
        }
        let speed = y > 2400 ? 60 * 0.8 : 60;
        vx = Math.cos(data) * speed;
        vy = Math.sin(data) * speed;
        x += vx;
        y += vy;
        socket.emit('a');
        socket.emit('3', [id, x, y, -2.26, -1, 0, 0, null, 0, 0, 0, 0]);
      });
      socket.on('14', function (data) {
        console.log('ping!!!', arguments);
      });
    });
  });
}
*/
repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a)); // jshint ignore: line
    } catch (e) {
      cb(e);
    }
  }
});
<commit_msg>Boundaries<commit_after>'use strict';

const repl = require('repl');
const io = require('socket.io');

let randInt = (min, max) => Math.floor(Math.random() * (max - min)) + min;
let randChoose = choices => choices[randInt(0, choices.length)];
class Player {
  constructor(server, id) {
    let config = server.config;
    this.id = id;
    this.clan = null;
    this.server = server;
    this.untilSend = 1;

    this.lastPing = new Date('2017-07-09 5:57:00').getTime();

    this.name = 'unknown';
    this.skin = 0;
    this.size = config.playerScale;
    this.viewedObjects = [];

    this.aimAngle = 0;
    this.movement = null;
    this.kill();
  }
  updateMovement(delta) {
    let config = this.server.config;
    let tx = 0;
    let ty = 0;
    if (this.movement != null) {
      tx = Math.cos(this.movement);
      ty = Math.sin(this.movement);
    }
    this.peek();
    this.vx *= Math.pow(config.playerDecel, delta);
    this.vy *= Math.pow(config.playerDecel, delta);
    this.vx += tx * config.playerSpeed * delta * this.size / 2;
    this.vy += ty * config.playerSpeed * delta * this.size / 2;
    this.x += this.vx;
    this.y += this.vy;
    (this.x < 0) && (this.x = 0);
    (this.x > config.mapScale) && (this.x = config.mapScale);
    (this.y < 0) && (this.y = 0);
    (this.y > config.mapScale) && (this.y = config.mapScale);
  }
  update(delta) {
    if (this.alive) {
      this.updateMovement(delta);
      this.untilSend--;
      if (!this.untilSend) {
        this.untilSend = this.server.config.clientSendRate;
        this.sendPosition();
      }
    }
  }
  peek() {
    let old = this.viewedObjects;
    let view = this.server.viewObjects(this.x, this.y);
    let sending = [];
    for (let i of view) {
      if (old[i.id]) continue;
      old[i.id] = true;
      sending.push(...i.data);
    }
    if (sending.length) {
      console.log(2)
      this.socket.emit('6', sending)
    }
  }
  sendPosition() {
    let socket = this.socket;
    socket.emit('a');
    socket.emit('3', [
      this.id,
      this.x,
      this.y, -2.26,-1,0,0,null,0,0,0,0]);
  }
  link(socket) {
    let config = this.server.config;
    this.socket = socket;
    socket.once('error', err => {
      console.log(err);
      this.destroy();
    });

    let emitAll = (...arg) => {
      try {
        socket.broadcast.emit(...arg)
        socket.emit(...arg)
      } catch (e) {
      }
    }

    socket.on('2', angle => this.aimAngle = angle);
    socket.on('3', angle => this.movement = angle);

    socket.on('14', data => {
      let now = Date.now();
      let dif = now - this.lastPing;
      if (dif > config.mapPingTime) {
        this.lastPing = now;
        emitAll('p', this.x, this.y);
      }
    });

    socket.on('ch', msg => emitAll('ch', this.id, msg));
    socket.once('disconnect', () => this.destroy());
    socket.emit('id', {
      teams: this.server.clans
    });
    socket.on('1', data => {
      this.name = data.name.length > 15 || !data.name ? 'unknown' : data.name;
      this.skin = data.skin;
      this.spawn();
      this.peek();
    });
  }
  destroy() {
    this.kill();
    this.server.remove(this.id);
    this.socket.disconnect();
  }
  kill() {
    this.alive = false;
    this.x = 0;
    this.y = 0;
    this.slowDown();
  }
  slowDown() {
    this.vx = 0;
    this.vy = 0;
  }
  spawn() {
    let config = this.server.config;
    let socket = this.socket;
    this.alive = true;
    let { x, y } = this.server.allocatePosition(this.size);
    this.x = x;
    this.y = y;
    this.slowDown();
    socket.emit('1', this.id);
    socket.emit('2', [socket.id,this.id,this.name,this.x,this.y,0,100,100,this.size,this.skin],true);
  }
  hitResource(type) {

  }
}
class Resource {
  constructor(server, id, x, y, size, type) {
    let config = server.config;
    this.x = x;
    this.y = y;
    this.id = id;
    this.type = config.resourceTypes.indexOf(type);
    this.size = size;
    this.init();
  }
  reward(by) {
    by.hitResource(this.type);
  }
  init() {
    this.data = [
      this.id,
      this.x,
      this.y,
      0,
      this.size,
      this.type,
      null,
      -1,
    ];
  }
}
class Server {
  constructor(config) {
    this.config = config;
    this.players = Array(config.maxPlayers).fill(null);
    this.lastRun = Date.now();
    this.clans = [];
    this.objects = [];
    setInterval(() => this.update(), config.serverUpdateRate);
    this.generateWorld();
  }
  remove(sid) {
    this.players[sid] = null;
  }
  update() {
    let now = Date.now();
    let delta = now - this.lastRun;
    this.lastRun = now;
    for (let i of this.players) {
      if (i != null) {
        i.update(delta);
      }
    }
  }
  viewObjects(x, y) {
    let config = this.config;
    let visibles = [];
    let width = config.maxScreenWidth;
    let height = config.maxScreenHeight;
    for (let i of this.objects)
      if (
        i.y + height > y &&
        i.y - height < y &&
        i.x + width > x &&
        i.x - width < x
      ) visibles.push(i);
    return visibles;
  }
  viewPlayers(x, y) {
    let config = this.config;
    let visibles = [];
    let width = config.maxScreenWidth;
    let height = config.maxScreenHeight;
    for (let i of this.players)
      if (
        i.y + height > y &&
        i.y - height < y &&
        i.x + width > x &&
        i.x - width < x
      ) visibles.push(i);
    return visibles;
  }
  generateWorld() {
    let config = this.config;
    let areaCount = config.areaCount;
    let mapScale = config.mapScale;
    let riverWidth = config.riverWidth;
    let areaSize = mapScale / areaCount;
    let all = [];
    let id = 0;
    for (let afx = 0, atx = 1; afx < areaCount; afx++, atx++) {
      for (let afy = 0, aty = 1; afy < areaCount; afy++, aty++) {
        for (let i = 0; i < config.treesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          if (y < mapScale - config.snowBiomeTop && (
              y > (mapScale + riverWidth) / 2 ||
              y < (mapScale - riverWidth) / 2)
            ) all.push(new Resource(this, id++, x, y, randChoose(config.treeScales), 'wood'));
        }
        for (let i = 0; i < config.bushesPerArea; i++) {
          let x = randInt(areaSize * afx, areaSize * atx);
          let y = randInt(areaSize * afy, areaSize * aty);
          if (y > (mapScale + riverWidth) / 2 ||
              y < (mapScale - riverWidth) / 2
            ) all.push(new Resource(this, id++, x, y, randChoose(config.bushScales), 'food'));
        }
      }
    }
    for (let i = 0; i < config.totalRocks; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      all.push(new Resource(this, id++, x, y, randChoose(config.rockScales), 'stone'));
    }
    for (let i = 0; i < config.goldOres; i++) {
      let x = randInt(0, mapScale);
      let y = randInt(0, mapScale);
      if (y > (mapScale + riverWidth) / 2 ||
          y < (mapScale - riverWidth) / 2
      ) {
        i--;
        continue;
      }
      all.push(new Resource(this, id++, x, y, 50, 'points'));
    }
    this.objects = all;
  }
  allocatePosition(size) {
    let scale = this.config.mapScale;
    let x = 0;
    let y = 0;
    while (true) {
      x = randInt(0, scale);
      y = randInt(0, scale);
      if (true) { // check if there's nothing overlapping
        break;
      }
    }
    return { x, y };
  }
  handle(socket) {
    for (let i = 0; i < this.players.length; i++) {
      if (this.players[i] == null) {
        let player = new Player(this, i);
        player.link(socket);
        this.players[i] = player;
        break;
      }
    }
  }
}

let app = new Server({
  mapScale: 14400,
  maxPlayers: 50,
  clientSendRate: 5,
  serverUpdateRate: 9,
  playerDecel: 0.993,
  playerSpeed: 0.0016,
  playerScale: 35,
  areaCount: 7,
  treesPerArea: 9,
  bushesPerArea: 3,
  totalRocks: 32,
  goldOres: 7,
  resourceTypes: ['wood', 'food', 'stone', 'points'],
  treeScales: [140, 145, 150, 155],
  bushScales: [80, 85, 95],
  rockScales: [80, 85, 90],
  maxScreenWidth: 1920,
  maxScreenHeight: 1080,
  snowBiomeTop: 2400,
  riverWidth: 724,
  mapPingTime: 2200,
});

for (let i = 5000; i <= 5010; i++) {
  io(i).on('connection', socket => app.handle(socket));
}
/*
let teams = [];
let sockets = [];
  io(i).on('connection', function (socket) {
    let emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg);
        socket.emit(...arg);
      } catch (e) {
        sockets.forEach(a => a.emit(...arg));
      }
    };
    sockets.push(socket);
    socket.on('1', function (data) {
      let id = 27;
      let name = data.name.length > 15 ? 'unknown' : data.name;
      socket.emit('id', {
        'teams': teams
      });
      socket.emit('1', id);
      socket.emit('mm', 0);
      socket.emit('3', []);
      let x = randInt(0, config.mapScale);
      let y = randInt(0, config.mapScale);
      let userteam = null;
      let last = 0;
      socket.emit('2', ['a3Pm5dMzeKOjc5gvAJEF', id, name, x, 7200, 0, 100, 100, 35, data.skin], true);
      socket.emit('5', [27, data.name, 9001]); //[5,'RIP',31988,45,'KADEJO503',23404,34,'winter wolf',4821,28,'Godenot',4500,33,'Arena Closer',3000,32,'LightTheif',2940,6,'CarlosKoS-_-16',2800,4,'GD desconhecido',2635,35,'jack black GD',2357,19,'AMIGO BOM',1623])
      socket.emit('6', [
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353, 4103, 13436, 0, 80, 2, null, -1,
        339, 2498, 14155, 0, 90, 2, null, -1
      ]);
      socket.emit('8', 2.6, 28);
      socket.on('ch', data => {
        emit('ch', id, data);
      });
      socket.on('8', data => {
        console.log('CLAN CREATE REQUEST:', data);
        teams.push([{
          'sid': data,
          'owner': id
        }]);
        let userteam = data;
        emit('st', data, true);
      });
      socket.on('3', function (data) {
        if (data == null) {
          vx = vy = 0;
          return;
        } else if (x < 0 || x > config.mapScale || y < 0 || y > config.mapScale) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;
        }
        let speed = y > 2400 ? 60 * 0.8 : 60;
        vx = Math.cos(data) * speed;
        vy = Math.sin(data) * speed;
        x += vx;
        y += vy;
        socket.emit('a');
        socket.emit('3', [id, x, y, -2.26, -1, 0, 0, null, 0, 0, 0, 0]);
      });
      socket.on('14', function (data) {
        console.log('ping!!!', arguments);
      });
    });
  });
}
*/
repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a)); // jshint ignore: line
    } catch (e) {
      cb(e);
    }
  }
});
<|endoftext|>


<commit_before>"use strict"

const path = require("path");
const spawn = require("child_process").spawn
const electronPath = require("electron");

var scrapmanPath = path.join(__dirname, './lib/scrapman.js');

let child = spawn(electronPath, [scrapmanPath], { stdio: ["pipe", "pipe", "pipe", "ipc"] });
let scrapmanIsReady = false;
let onceReadyActionsQueue = [];
let actionsQueue = [];
let currentConcurrentOperations = 0;

let config = {
    maxConcurrentOperations: 50
}

const ipcManager_parent = require("ipc-messages-manager").parent;

ipcManager_parent.send(child, "notify-when-ready", null, function() {
    scrapmanIsReady = true;
    executeOnceReadyQueue();
});

// add action to once ready queue
let queueOnceReadyAction = (action, params, callback) => {
    onceReadyActionsQueue.push({ action, params, callback });
}

let executeOnceReadyQueue = () => {
    // execute all pending actions, this will be executed once the "scrapman"(Electron) instance is ready
    onceReadyActionsQueue.forEach((action) => {
        // try to send the message to the child
        executeAction(action.action, action.params, action.callback);
    });

    // clean up the queue
    onceReadyActionsQueue = [];
}

let executeRemainingQueuedActions = () => {
    if(actionsQueue.length > 0){
        let queuedAction = actionsQueue.shift();
        executeAction(queuedAction.action, queuedAction.params, queuedAction.callback);
    }
}

//this function limits concurrent execution of several actions,
//to prevent the Three Stooges Syndrome (clogging above 50 concurrent operations)
let executeAction = (action, params, callback) => {
    // check if more concurrent operations can be executed
    if(currentConcurrentOperations < config.maxConcurrentOperations){

        // increment the "councurrent operations" counter
        currentConcurrentOperations++;

        // send the actual message to the child
        ipcManager_parent.send(child, action, params, function(results){
            callback(results);
            // once this concurrent operation finished, decrement the "concurrent oprations" counter
            currentConcurrentOperations--;
            // if there are pending operations on queue to be performed, then process them.
            executeRemainingQueuedActions();
        });

    }else{
        // all concurrent slots are occupied, queue this operation.
        actionsQueue.push({action, params, callback});
    }
}

let load = (url, callback) => {
    if (scrapmanIsReady) {
        // if scrapman instance is ready, try to send the action to the child
        executeAction("load", {url}, callback);
    } else {
        // if the scrapman instance is not ready yet, then add the function
        // to the queue that will get executed once it's ready
        queueOnceReadyAction("load", {url}, callback);
    }
}

let configure = (newConfig)=>{
    config = Object.assign({}, config, newConfig);
}

module.exports = {
    load,
    configure
}
<commit_msg>get the correct Electron executable's path to spawn the child process<commit_after>"use strict"

const path = require("path");
const spawn = require("child_process").spawn
const electron = require("electron");

// get the electron executable path to spawn a child process with it,
// normally "require('electron')" will return its path, but if it's executed
// on an Electron context (i.e. using Scrapman within another Electron app)
// "require('electron')" will return the current Electron instance,
// if this is the case then get the path from the instance itself.
let electronPath = typeof electron === "string" ? electron : electron.app.getPath("exe");

var scrapmanPath = path.join(__dirname, './lib/scrapman.js');

let child = spawn(electronPath, [scrapmanPath], { stdio: ["pipe", "pipe", "pipe", "ipc"] });
let scrapmanIsReady = false;
let onceReadyActionsQueue = [];
let actionsQueue = [];
let currentConcurrentOperations = 0;

let config = {
    maxConcurrentOperations: 50
}

const ipcManager_parent = require("ipc-messages-manager").parent;

ipcManager_parent.send(child, "notify-when-ready", null, function() {
    scrapmanIsReady = true;
    executeOnceReadyQueue();
});

// add action to once ready queue
let queueOnceReadyAction = (action, params, callback) => {
    onceReadyActionsQueue.push({ action, params, callback });
}

let executeOnceReadyQueue = () => {
    // execute all pending actions, this will be executed once the "scrapman"(Electron) instance is ready
    onceReadyActionsQueue.forEach((action) => {
        // try to send the message to the child
        executeAction(action.action, action.params, action.callback);
    });

    // clean up the queue
    onceReadyActionsQueue = [];
}

let executeRemainingQueuedActions = () => {
    if(actionsQueue.length > 0){
        let queuedAction = actionsQueue.shift();
        executeAction(queuedAction.action, queuedAction.params, queuedAction.callback);
    }
}

//this function limits concurrent execution of several actions,
//to prevent the Three Stooges Syndrome (clogging above 50 concurrent operations)
let executeAction = (action, params, callback) => {
    // check if more concurrent operations can be executed
    if(currentConcurrentOperations < config.maxConcurrentOperations){

        // increment the "councurrent operations" counter
        currentConcurrentOperations++;

        // send the actual message to the child
        ipcManager_parent.send(child, action, params, function(results){
            callback(results);
            // once this concurrent operation finished, decrement the "concurrent oprations" counter
            currentConcurrentOperations--;
            // if there are pending operations on queue to be performed, then process them.
            executeRemainingQueuedActions();
        });

    }else{
        // all concurrent slots are occupied, queue this operation.
        actionsQueue.push({action, params, callback});
    }
}

let load = (url, callback) => {
    if (scrapmanIsReady) {
        // if scrapman instance is ready, try to send the action to the child
        executeAction("load", {url}, callback);
    } else {
        // if the scrapman instance is not ready yet, then add the function
        // to the queue that will get executed once it's ready
        queueOnceReadyAction("load", {url}, callback);
    }
}

let configure = (newConfig)=>{
    config = Object.assign({}, config, newConfig);
}

module.exports = {
    load,
    configure
}
<|endoftext|>


<commit_before>// wrapper for nimoy!
<commit_msg>fix index for new nimoy methods<commit_after>// quickstart wrapper for nimoy!

var nimoy = require('./nimoy')
var configFlag = process.argv[2]

var n = !(configFlag)
  ? nimoy(require('./config.json'))
  : nimoy(require(process.argv[2]))

n.compile().boot()

n.on('boot', function () {
  console.log('nimoy running!')
})
<|endoftext|>


<commit_before>'use strict';

/**
 * Simplified http request.
 * (C) 2013-2014 MediaSmart Mobile.
 */

// requires
var http = require('http');
var https = require('https');
var urlLib = require('url');

/**
 * Access a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.get = function(url, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	send(options, params, callback);
};

/**
 * Post to a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- json: the object to send, can be a JSON string.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.post = function(url, json, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	options.method = 'POST';
	if (typeof json == 'object')
	{
		params.body = JSON.stringify(json);
		options.headers = {
			'Content-Type': 'application/json',
			'Content-Length': options.body.length,
		};
	}
	else
	{
		params.body = json;
		options.headers = {
			'Content-Type': 'text/plain',
			'Content-Length': options.body.length,
		};
	}
	send(options, params, callback);
};

function send(options, params, callback)
{
	callback = callback || function() {};
	options.headers = options.headers || {};
	options.headers['user-agent'] = 'node.js basic-request bot';
	options.agent = null;
	sendWithRetries(params.retries, options, params, callback);
}

function sendWithRetries(retries, options, params, callback)
{
	var finished = false;
	var protocol = http;
	if (options.protocol == 'https:')
	{
		protocol = https;
	}
	var request = protocol.get(options, function(response)
	{
		if (response.statusCode == 301 || response.statusCode == 302)
		{
			// follow redirection
			var location = response.headers.location;
			request.abort();
			return exports.get(location, callback);
		}
		if (response.statusCode != 200)
		{
			finished = true;
			request.abort();
			return callback('Invalid status code ' + response.statusCode, {statusCode: response.statusCode});
		}
		var body = '';
		response.on('data', function (chunk)
		{
			body += chunk;
		});
		response.on('error', function(error)
		{
			finished = true;
			return callback('Error reading response: ' + error, {readingResponse: true});
		});
		response.on('end', function()
		{
			if (finished)
			{
				return;
			}
			request.end();
			return callback(null, body);
		});
	});
	request.on('error', function(error)
	{
		finished = true;
		return callback('Error sending request: ' + error, {sendingRequest: true});
	});
	if (params.body)
	{
		request.write(params.body);
	}
	request.end();
}

// show API if invoked directly
if (__filename == process.argv[1])
{
	console.log('Use in your code as:');
	console.log('  request.get(url, function(error, body) {});');
}

<commit_msg>Bug fix: send correct length.<commit_after>'use strict';

/**
 * Simplified http request.
 * (C) 2013-2014 MediaSmart Mobile.
 */

// requires
var http = require('http');
var https = require('https');
var urlLib = require('url');

/**
 * Access a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.get = function(url, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	send(options, params, callback);
};

/**
 * Post to a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- json: the object to send, can be a JSON string.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.post = function(url, json, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	options.method = 'POST';
	if (typeof json == 'object')
	{
		params.body = JSON.stringify(json);
		options.headers = {
			'Content-Type': 'application/json',
			'Content-Length': params.body.length,
		};
	}
	else
	{
		params.body = json;
		options.headers = {
			'Content-Type': 'text/plain',
			'Content-Length': params.body.length,
		};
	}
	send(options, params, callback);
};

function send(options, params, callback)
{
	callback = callback || function() {};
	options.headers = options.headers || {};
	options.headers['user-agent'] = 'node.js basic-request bot';
	options.agent = null;
	sendWithRetries(params.retries, options, params, callback);
}

function sendWithRetries(retries, options, params, callback)
{
	var finished = false;
	var protocol = http;
	if (options.protocol == 'https:')
	{
		protocol = https;
	}
	var request = protocol.get(options, function(response)
	{
		if (response.statusCode == 301 || response.statusCode == 302)
		{
			// follow redirection
			var location = response.headers.location;
			request.abort();
			return exports.get(location, callback);
		}
		if (response.statusCode != 200)
		{
			finished = true;
			request.abort();
			return callback('Invalid status code ' + response.statusCode, {statusCode: response.statusCode});
		}
		var body = '';
		response.on('data', function (chunk)
		{
			body += chunk;
		});
		response.on('error', function(error)
		{
			finished = true;
			return callback('Error reading response: ' + error, {readingResponse: true});
		});
		response.on('end', function()
		{
			if (finished)
			{
				return;
			}
			request.end();
			return callback(null, body);
		});
	});
	request.on('error', function(error)
	{
		finished = true;
		return callback('Error sending request: ' + error, {sendingRequest: true});
	});
	if (params.body)
	{
		request.write(params.body);
	}
	request.end();
}

// show API if invoked directly
if (__filename == process.argv[1])
{
	console.log('Use in your code as:');
	console.log('  request.get(url, function(error, body) {});');
}

<|endoftext|>