<commit_before>'use strict';

import arrayEach from 'lodash/_arrayEach';
import forOwn from 'lodash/forOwn';
import indexOf from 'lodash/indexOf';
import isArray from 'lodash/isArray';
import okeys from 'lodash/keys';
import noop from 'lodash/noop';
import once from './internal/once';
import rest from 'lodash/rest';

import onlyOnce from './internal/onlyOnce';

/**
 * Determines the best order for running the functions in `tasks`, based on
 * their requirements. Each function can optionally depend on other functions
 * being completed first, and each function is run as soon as its requirements
 * are satisfied.
 *
 * If any of the functions pass an error to their callback, the `auto` sequence
 * will stop. Further tasks will not execute (so any other functions depending
 * on it will not run), and the main `callback` is immediately called with the
 * error.
 *
 * Functions also receive an object containing the results of functions which
 * have completed so far as the first argument, if they have dependencies. If a
 * task function has no dependencies, it will only be passed a callback.
 *
 * @name auto
 * @static
 * @memberOf async
 * @category Control Flow
 * @param {Object} tasks - An object. Each of its properties is either a
 * function or an array of requirements, with the function itself the last item
 * in the array. The object's key of a property serves as the name of the task
 * defined by that property, i.e. can be used when specifying requirements for
 * other tasks. The function receives one or two arguments:
 * * a `results` object, containing the results of the previously executed
 *   functions, only passed if the task has any dependencies,
 * * a `callback(err, result)` function, which must be called when finished,
 *   passing an `error` (which can be `null`) and the result of the function's
 *   execution.
 * @param {number} [concurrency=Infinity] - An optional `integer` for
 * determining the maximum number of tasks that can be run in parallel. By
 * default, as many as possible.
 * @param {Function} [callback] - An optional callback which is called when all
 * the tasks have been completed. It receives the `err` argument if any `tasks`
 * pass an error to their callback. Results are always returned; however, if an
 * error occurs, no further `tasks` will be performed, and the results object
 * will only contain partial results. Invoked with (err, results).
 * @example
 *
 * async.auto({
 *     // this function will just be passed a callback
 *     readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
 *     showData: ['readData', function(results, cb) {
 *         // results.readData is the file's contents
 *         // ...
 *     }]
 * }, callback);
 *
 * async.auto({
 *     get_data: function(callback) {
 *         console.log('in get_data');
 *         // async code to get some data
 *         callback(null, 'data', 'converted to array');
 *     },
 *     make_folder: function(callback) {
 *         console.log('in make_folder');
 *         // async code to create a directory to store a file in
 *         // this is run at the same time as getting the data
 *         callback(null, 'folder');
 *     },
 *     write_file: ['get_data', 'make_folder', function(results, callback) {
 *         console.log('in write_file', JSON.stringify(results));
 *         // once there is some data and the directory exists,
 *         // write the data to a file in the directory
 *         callback(null, 'filename');
 *     }],
 *     email_link: ['write_file', function(results, callback) {
 *         console.log('in email_link', JSON.stringify(results));
 *         // once the file is written let's email a link to it...
 *         // results.write_file contains the filename returned by write_file.
 *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
 *     }]
 * }, function(err, results) {
 *     console.log('err = ', err);
 *     console.log('results = ', results);
 * });
 */
export default function (tasks, concurrency, callback) {
    if (typeof concurrency === 'function') {
        // concurrency is optional, shift the args.
        callback = concurrency;
        concurrency = null;
    }
    callback = once(callback || noop);
    var keys = okeys(tasks);
    var numTasks = keys.length;
    if (!numTasks) {
        return callback(null);
    }
    if (!concurrency) {
        concurrency = numTasks;
    }

    var results = {};
    var runningTasks = 0;
    var hasError = false;

    var listeners = {};

    var readyTasks = [];

    // for cycle detection:
    var readyToCheck = []; // tasks that have been identified as reachable
    // without the possibility of returning to an ancestor task
    var uncheckedDependencies = {};

    forOwn(tasks, function (task, key) {
        if (!isArray(task)) {
            // no dependencies
            enqueueTask(key, [task]);
            readyToCheck.push(key);
            return;
        }

        var dependencies = task.slice(0, task.length - 1);
        var remainingDependencies = dependencies.length;
        if (!remainingDependencies) {
            enqueueTask(key, [task]);
            readyToCheck.push(key);
        }
        uncheckedDependencies[key] = remainingDependencies;

        arrayEach(dependencies, function (dependencyName) {
            addListener(dependencyName, function () {
                remainingDependencies--;
                if (remainingDependencies === 0) {
                    enqueueTask(key, task);
                }
            });
        });
    });

    checkForDeadlocks();
    processQueue();

    function enqueueTask(key, task) {
        readyTasks.push(function () {
            runTask(key, task);
        });
    }

    function processQueue() {
        if (readyTasks.length === 0 && runningTasks === 0) {
            return callback(null, results);
        }
        while(readyTasks.length && runningTasks < concurrency) {
            var run = readyTasks.shift();
            run();
        }

    }

    function addListener(taskName, fn) {
        var taskListeners = listeners[taskName];
        if (!taskListeners) {
            taskListeners = listeners[taskName] = [];
        }

        taskListeners.push(fn);
    }

    function taskComplete(taskName) {
        var taskListeners = listeners[taskName] || [];
        arrayEach(taskListeners, function (fn) {
            fn();
        });
        processQueue();
    }

    function runTask(key, task) {
        if (hasError) return;

        var taskCallback = onlyOnce(rest(function(err, args) {
            runningTasks--;
            if (args.length <= 1) {
                args = args[0];
            }
            if (err) {
                var safeResults = {};
                forOwn(results, function(val, rkey) {
                    safeResults[rkey] = val;
                });
                safeResults[key] = args;
                hasError = true;
                listeners = [];

                callback(err, safeResults);
            } else {
                results[key] = args;
                taskComplete(key);
            }
        }));

        runningTasks++;
        var taskFn = task[task.length - 1];
        if (task.length > 1) {
            taskFn(results, taskCallback);
        } else {
            taskFn(taskCallback);
        }
    }

    function checkForDeadlocks() {
        // Kahn's algorithm
        // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
        // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
        var currentTask;
        var counter = 0;
        while (readyToCheck.length) {
            currentTask = readyToCheck.pop();
            counter++;
            arrayEach(getDependents(currentTask), function (dependent) {
                if (!(--uncheckedDependencies[dependent])) {
                    readyToCheck.push(dependent);
                }
            });
        }

        if (counter !== numTasks) {
            throw new Error(
                'async.auto cannot execute tasks due to a recursive dependency'
            );
        }
    }

    function getDependents(taskName) {
        var result = [];
        forOwn(tasks, function (task, key) {
            if (isArray(task) && indexOf(task, taskName) >= 0) {
                result.push(key);
            }
        });
        return result;
    }
}
<commit_msg>Re-introduce nonexistent dependency check<commit_after>'use strict';

import arrayEach from 'lodash/_arrayEach';
import forOwn from 'lodash/forOwn';
import indexOf from 'lodash/indexOf';
import isArray from 'lodash/isArray';
import okeys from 'lodash/keys';
import noop from 'lodash/noop';
import once from './internal/once';
import rest from 'lodash/rest';

import onlyOnce from './internal/onlyOnce';

/**
 * Determines the best order for running the functions in `tasks`, based on
 * their requirements. Each function can optionally depend on other functions
 * being completed first, and each function is run as soon as its requirements
 * are satisfied.
 *
 * If any of the functions pass an error to their callback, the `auto` sequence
 * will stop. Further tasks will not execute (so any other functions depending
 * on it will not run), and the main `callback` is immediately called with the
 * error.
 *
 * Functions also receive an object containing the results of functions which
 * have completed so far as the first argument, if they have dependencies. If a
 * task function has no dependencies, it will only be passed a callback.
 *
 * @name auto
 * @static
 * @memberOf async
 * @category Control Flow
 * @param {Object} tasks - An object. Each of its properties is either a
 * function or an array of requirements, with the function itself the last item
 * in the array. The object's key of a property serves as the name of the task
 * defined by that property, i.e. can be used when specifying requirements for
 * other tasks. The function receives one or two arguments:
 * * a `results` object, containing the results of the previously executed
 *   functions, only passed if the task has any dependencies,
 * * a `callback(err, result)` function, which must be called when finished,
 *   passing an `error` (which can be `null`) and the result of the function's
 *   execution.
 * @param {number} [concurrency=Infinity] - An optional `integer` for
 * determining the maximum number of tasks that can be run in parallel. By
 * default, as many as possible.
 * @param {Function} [callback] - An optional callback which is called when all
 * the tasks have been completed. It receives the `err` argument if any `tasks`
 * pass an error to their callback. Results are always returned; however, if an
 * error occurs, no further `tasks` will be performed, and the results object
 * will only contain partial results. Invoked with (err, results).
 * @example
 *
 * async.auto({
 *     // this function will just be passed a callback
 *     readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
 *     showData: ['readData', function(results, cb) {
 *         // results.readData is the file's contents
 *         // ...
 *     }]
 * }, callback);
 *
 * async.auto({
 *     get_data: function(callback) {
 *         console.log('in get_data');
 *         // async code to get some data
 *         callback(null, 'data', 'converted to array');
 *     },
 *     make_folder: function(callback) {
 *         console.log('in make_folder');
 *         // async code to create a directory to store a file in
 *         // this is run at the same time as getting the data
 *         callback(null, 'folder');
 *     },
 *     write_file: ['get_data', 'make_folder', function(results, callback) {
 *         console.log('in write_file', JSON.stringify(results));
 *         // once there is some data and the directory exists,
 *         // write the data to a file in the directory
 *         callback(null, 'filename');
 *     }],
 *     email_link: ['write_file', function(results, callback) {
 *         console.log('in email_link', JSON.stringify(results));
 *         // once the file is written let's email a link to it...
 *         // results.write_file contains the filename returned by write_file.
 *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
 *     }]
 * }, function(err, results) {
 *     console.log('err = ', err);
 *     console.log('results = ', results);
 * });
 */
export default function (tasks, concurrency, callback) {
    if (typeof concurrency === 'function') {
        // concurrency is optional, shift the args.
        callback = concurrency;
        concurrency = null;
    }
    callback = once(callback || noop);
    var keys = okeys(tasks);
    var numTasks = keys.length;
    if (!numTasks) {
        return callback(null);
    }
    if (!concurrency) {
        concurrency = numTasks;
    }

    var results = {};
    var runningTasks = 0;
    var hasError = false;

    var listeners = {};

    var readyTasks = [];

    // for cycle detection:
    var readyToCheck = []; // tasks that have been identified as reachable
    // without the possibility of returning to an ancestor task
    var uncheckedDependencies = {};

    forOwn(tasks, function (task, key) {
        if (!isArray(task)) {
            // no dependencies
            enqueueTask(key, [task]);
            readyToCheck.push(key);
            return;
        }

        var dependencies = task.slice(0, task.length - 1);
        var remainingDependencies = dependencies.length;
        if (!remainingDependencies) {
            enqueueTask(key, [task]);
            readyToCheck.push(key);
        }
        uncheckedDependencies[key] = remainingDependencies;

        arrayEach(dependencies, function (dependencyName) {
            if (!tasks[dependencyName]) {
                throw new Error('async.auto task `' + key +
                    '` has a non-existent dependency in ' +
                    dependencies.join(', '));
            }
            addListener(dependencyName, function () {
                remainingDependencies--;
                if (remainingDependencies === 0) {
                    enqueueTask(key, task);
                }
            });
        });
    });

    checkForDeadlocks();
    processQueue();

    function enqueueTask(key, task) {
        readyTasks.push(function () {
            runTask(key, task);
        });
    }

    function processQueue() {
        if (readyTasks.length === 0 && runningTasks === 0) {
            return callback(null, results);
        }
        while(readyTasks.length && runningTasks < concurrency) {
            var run = readyTasks.shift();
            run();
        }

    }

    function addListener(taskName, fn) {
        var taskListeners = listeners[taskName];
        if (!taskListeners) {
            taskListeners = listeners[taskName] = [];
        }

        taskListeners.push(fn);
    }

    function taskComplete(taskName) {
        var taskListeners = listeners[taskName] || [];
        arrayEach(taskListeners, function (fn) {
            fn();
        });
        processQueue();
    }

    function runTask(key, task) {
        if (hasError) return;

        var taskCallback = onlyOnce(rest(function(err, args) {
            runningTasks--;
            if (args.length <= 1) {
                args = args[0];
            }
            if (err) {
                var safeResults = {};
                forOwn(results, function(val, rkey) {
                    safeResults[rkey] = val;
                });
                safeResults[key] = args;
                hasError = true;
                listeners = [];

                callback(err, safeResults);
            } else {
                results[key] = args;
                taskComplete(key);
            }
        }));

        runningTasks++;
        var taskFn = task[task.length - 1];
        if (task.length > 1) {
            taskFn(results, taskCallback);
        } else {
            taskFn(taskCallback);
        }
    }

    function checkForDeadlocks() {
        // Kahn's algorithm
        // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
        // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
        var currentTask;
        var counter = 0;
        while (readyToCheck.length) {
            currentTask = readyToCheck.pop();
            counter++;
            arrayEach(getDependents(currentTask), function (dependent) {
                if (!(--uncheckedDependencies[dependent])) {
                    readyToCheck.push(dependent);
                }
            });
        }

        if (counter !== numTasks) {
            throw new Error(
                'async.auto cannot execute tasks due to a recursive dependency'
            );
        }
    }

    function getDependents(taskName) {
        var result = [];
        forOwn(tasks, function (task, key) {
            if (isArray(task) && indexOf(task, taskName) >= 0) {
                result.push(key);
            }
        });
        return result;
    }
}
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	Snakeskin = require('snakeskin');

const
	{Vars} = Snakeskin;

module.exports = [
	/**
	 * Expands the `_` snippet as a `<${rootTag}>` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @param {string} rootTag
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * - rootTag = 'span'
	 *
	 * /// <span class="foo"><span class="bar"></span</span
	 * < _.foo
	 *   < _.bar
	 * ```
	 */
	function expandRootTag(tag, attrs, rootTag) {
		if (tag === '_') {
			if (rootTag) {
				return rootTag;
			}

			attrs[':is'] = ['rootTag'];
			return 'tag';
		}

		return tag;
	},

	/**
	 * Expands the `:section` and `:/section` snippets.
	 * These snippets help to use semantics HTML tags, like `article` or `section` and don't care about `h` types.
	 *
	 * @param {string} tag
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <article><h2>Foo</h2></article>
	 * < article:section
	 *   < h1
	 *     Foo
	 * < :/section
	 * ```
	 */
	function expandSection(tag) {
		Vars.h = Vars.h ?? 0;

		if (/^(.*):section$/.test(tag)) {
			if (Vars.h < 6) {
				Vars.h++;
			}

			return RegExp.$1.trim() || 'section';
		}

		if (/^(.*):-section$/.test(tag)) {
			if (Vars.h > 0) {
				Vars.h--;
			}

			return '?';
		}

		if (/^h(\d)$/.test(tag)) {
			const v = Number(RegExp.$1) + Vars.h;
			return `h${v < 6 ? v : 6}`;
		}

		return tag;
	},

	/**
	 * Expands the `a:void` snippet as a `<a href="javascript:void(0)">` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <a class="bar" href="javascript:void(0)"></a>
	 * < a:void.bar
	 * ```
	 */
	function expandVoidLink(tag, attrs) {
		if (/^a:void$/.test(tag)) {
			attrs.href = ['javascript:void(0)'];
			return 'a';
		}

		return tag;
	},

	/**
	 * Expands the `button:link` snippet as a `<button class="a">` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <button class="bar a"></button>
	 * < button:link.bar
	 * ```
	 */
	function expandButtonLink(tag, attrs) {
		if (/^button:a$/.test(tag)) {
			attrs.type = ['button'];
			attrs.class = (attrs.class || []).concat('a');
			return 'button';
		}

		return tag;
	},

	/**
	 * Expands the `@component` snippet as a `<component v4-flyweight-component>` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <span v4-flyweight-component="b-button"></span>
	 * < @b-button
	 * ```
	 */
	function expandFlyweightComponent(tag, attrs) {
		if (tag[0] === '@') {
			attrs['v4-flyweight-component'] = [tag.slice(1)];
			attrs[':instance-of'] = attrs['v4-flyweight-component'];
			return 'span';
		}

		return tag;
	}
];
<commit_msg>Fixed providing of `rootTag`<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	Snakeskin = require('snakeskin');

const
	{Vars} = Snakeskin;

module.exports = [
	/**
	 * Expands the `_` snippet as a `<${rootTag}>` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @param {string} rootTag
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * - rootTag = 'span'
	 *
	 * /// <span class="foo"><span class="bar"></span</span
	 * < _.foo
	 *   < _.bar
	 * ```
	 */
	function expandRootTag(tag, attrs, rootTag) {
		if (tag === '_') {
			if (rootTag) {
				return rootTag;
			}

			attrs[':is'] = ["rootTag || 'div'"];
			return 'tag';
		}

		return tag;
	},

	/**
	 * Expands the `:section` and `:/section` snippets.
	 * These snippets help to use semantics HTML tags, like `article` or `section` and don't care about `h` types.
	 *
	 * @param {string} tag
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <article><h2>Foo</h2></article>
	 * < article:section
	 *   < h1
	 *     Foo
	 * < :/section
	 * ```
	 */
	function expandSection(tag) {
		Vars.h = Vars.h ?? 0;

		if (/^(.*):section$/.test(tag)) {
			if (Vars.h < 6) {
				Vars.h++;
			}

			return RegExp.$1.trim() || 'section';
		}

		if (/^(.*):-section$/.test(tag)) {
			if (Vars.h > 0) {
				Vars.h--;
			}

			return '?';
		}

		if (/^h(\d)$/.test(tag)) {
			const v = Number(RegExp.$1) + Vars.h;
			return `h${v < 6 ? v : 6}`;
		}

		return tag;
	},

	/**
	 * Expands the `a:void` snippet as a `<a href="javascript:void(0)">` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <a class="bar" href="javascript:void(0)"></a>
	 * < a:void.bar
	 * ```
	 */
	function expandVoidLink(tag, attrs) {
		if (/^a:void$/.test(tag)) {
			attrs.href = ['javascript:void(0)'];
			return 'a';
		}

		return tag;
	},

	/**
	 * Expands the `button:link` snippet as a `<button class="a">` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <button class="bar a"></button>
	 * < button:link.bar
	 * ```
	 */
	function expandButtonLink(tag, attrs) {
		if (/^button:a$/.test(tag)) {
			attrs.type = ['button'];
			attrs.class = (attrs.class || []).concat('a');
			return 'button';
		}

		return tag;
	},

	/**
	 * Expands the `@component` snippet as a `<component v4-flyweight-component>` tag
	 *
	 * @param {string} tag
	 * @param {!Object} attrs
	 * @returns {string}
	 *
	 * @example
	 * ```
	 * /// <span v4-flyweight-component="b-button"></span>
	 * < @b-button
	 * ```
	 */
	function expandFlyweightComponent(tag, attrs) {
		if (tag[0] === '@') {
			attrs['v4-flyweight-component'] = [tag.slice(1)];
			attrs[':instance-of'] = attrs['v4-flyweight-component'];
			return 'span';
		}

		return tag;
	}
];
<|endoftext|>


<commit_before>function Ball(params) {
  this.currentPosition  = 0;
  this.nextPosition     = 0;
  this.board            = params['board'];
  this.x                = 450;
  this.y                = 180;
  this.targetX          = 0;
  this.xVelocity        = 0;
  this.yVelocity        = 0;
  this.context          = params['context'];
  this.jumping          = false;
  this.moveInterval     = 50;
  this.alive            = true;
}

Ball.prototype.update = function(tick) {
  if(tick % this.moveInterval === 0){
    this.move();
  }

  if (this.nextPosition === null && this.y < 950) {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    this.yVelocity += 0.5;
  } else if (this.nextPosition === null && this.y > 950) {
    this.die();
  } else if (this.x !== this.targetX) {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    if(this.jumping === true) {
      this.yVelocity += 0.5;
    }
  } else {
    this.jumping         = false;
    this.xVelocity       = 0;
    this.yVelocity       = 0;
    this.currentPosition = this.nextPosition;
  }
};

Ball.prototype.onCube = function(){
  return this.board.cubes[this.currentPosition] || this.board.cubes[0];
};

Ball.prototype.draw = function() {
  this.context.fillStyle = 'crimson';
	this.context.beginPath();
  this.context.arc(this.x, this.y-10, 15, 0, 2 * Math.PI, false);
  this.context.fill();
};

Ball.prototype.move = function(){
  var chance = Math.random();
  if (chance > 0.5) {
    this.downLeft();
  } else {
    this.downRight();
  }
};

Ball.prototype.die = function(){
  this.jumping = false;
  this.alive   = false;
};

Ball.prototype.downLeft = function() {
  this.targetX   = this.x - 40;
  this.xVelocity = -2;
  this.yVelocity = -1.75;
  this.jumping = true;
  this.nextPosition = this.onCube().downLeftId;
};

Ball.prototype.downRight = function() {
  this.targetX   = this.x + 40;
  this.xVelocity = +2;
  this.yVelocity = -1.75;
  this.jumping = true;
  this.nextPosition = this.onCube().downRightId;
};

module.exports = Ball;
<commit_msg>Remove space<commit_after>function Ball(params) {
  this.currentPosition  = 0;
  this.nextPosition     = 0;
  this.board            = params['board'];
  this.x                = 450;
  this.y                = 180;
  this.targetX          = 0;
  this.xVelocity        = 0;
  this.yVelocity        = 0;
  this.context          = params['context'];
  this.jumping          = false;
  this.moveInterval     = 50;
  this.alive            = true;
}

Ball.prototype.update = function(tick) {
  if(tick % this.moveInterval === 0){
    this.move();
  }

  if (this.nextPosition === null && this.y < 950) {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    this.yVelocity += 0.5;
  } else if (this.nextPosition === null && this.y > 950) {
    this.die();
  } else if (this.x !== this.targetX) {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    if(this.jumping === true) {
      this.yVelocity += 0.5;
    }
  } else {
    this.jumping         = false;
    this.xVelocity       = 0;
    this.yVelocity       = 0;
    this.currentPosition = this.nextPosition;
  }
};

Ball.prototype.onCube = function(){
  return this.board.cubes[this.currentPosition] || this.board.cubes[0];
};

Ball.prototype.draw = function() {
  this.context.fillStyle = 'crimson';
	this.context.beginPath();
  this.context.arc(this.x, this.y-10, 15, 0, 2 * Math.PI, false);
  this.context.fill();
};

Ball.prototype.move = function(){
  var chance = Math.random();
  if (chance > 0.5) {
    this.downLeft();
  } else {
    this.downRight();
  }
};

Ball.prototype.die = function(){
  this.jumping = false;
  this.alive   = false;
};

Ball.prototype.downLeft = function() {
  this.targetX   = this.x - 40;
  this.xVelocity = -2;
  this.yVelocity = -1.75;
  this.jumping = true;
  this.nextPosition = this.onCube().downLeftId;
};

Ball.prototype.downRight = function() {
  this.targetX   = this.x + 40;
  this.xVelocity = +2;
  this.yVelocity = -1.75;
  this.jumping = true;
  this.nextPosition = this.onCube().downRightId;
};

module.exports = Ball;
<|endoftext|>


<commit_before>import THREE from 'three';
import Pepper from '../lib/pepper';

// Three js constants
let context = {};
let camera = {};
let renderer;
let scene;
let effect;
let ghost;

const gameObjects = {
  disk: {},
  pOne: {},
  pTwo: {},
};

let tracker = {};

const torusGeo = new THREE.TorusGeometry(50, 20, 8, 8);
const sphereGeo = new THREE.SphereGeometry(50, 10, 10);
const trackerGeo = new THREE.CubeGeometry(500, 500, 2);
const basicMat = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const basicMat2 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const basicMat3 = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.2 });

const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  effect.setSize(window.innerWidth, window.innerHeight);
};

// SECTION
// PLAYER
// SECTION
const buildPlayer = (key) => {
  const current = gameObjects[key];
  const material = new THREE.MeshBasicMaterial();
  current.open = true;
  if (key === 'pOne') {
    current.mesh = new THREE.Mesh(torusGeo, basicMat);
    current.position = { x: 0, y: 0, z: -400 };
  }
  if (key === 'pTwo') {
    current.mesh = new THREE.Mesh(torusGeo, material);
    current.position = { x: 0, y: 0, z: 400 };
  }
  scene.add(current.mesh);
  current.mesh.translateX(current.position.x);
  current.mesh.translateY(current.position.y);
  current.mesh.translateZ(current.position.z);
};

const shootBall = player => {
  console.log('open');
  const vector = new THREE.Vector3(0, 0, 1);
  vector.applyQuaternion(player.mesh.quaternion);
  vector.multiplyScalar(12);
  console.log(vector);
  gameObjects.disk.velocity = vector;
  // after release
  gameObjects.disk.held = false;
  gameObjects.disk.currentOwner = null;
};

export const openHand = player => {
  if (!gameObjects[player].open) {
    gameObjects[player].open = true;
    gameObjects[player].mesh.scale.set(1, 1, 1);
    if (gameObjects.disk.held && gameObjects.disk.currentOwner === gameObjects[player]) {
      shootBall(gameObjects[player]);
    }
  }
};

export const closeHand = player => {
  if (gameObjects[player].open) {
    gameObjects[player].open = false;
    gameObjects[player].mesh.scale.set(0.4, 0.4, 0.4);
  }
};

export const updatePlayerTransform = (player, roll, yaw, pitch, handPos) => {
  const current = gameObjects[player];
  current.mesh.rotation.set(pitch, -yaw, roll);
  current.mesh.position.setX(handPos.x * 300);
  current.mesh.position.setY(handPos.y * 300 - 150);
  current.position.x = handPos.x * 300;
  current.position.y = handPos.y * 300 - 150;
};

// SECTION
// BALL
// SECTION
const buildBall = () => {
  const ball = gameObjects.disk;
  ball.mesh = new THREE.Mesh(sphereGeo, basicMat2);
  ball.position = { x: 0, y: 0, z: 0 };
  ball.velocity = { x: 0, y: 0, z: 6 };
  scene.add(ball.mesh);
  ball.held = false;
};

const checkBounds = ball => {
  const range = 350;
  if (ball.position.x >= (range - 100) || ball.position.x < -(range - 100)) {
    ball.velocity.x *= -1;
  }
  if (ball.position.y >= (range - 100) || ball.position.y < -(range - 100)) {
    ball.velocity.y *= -1;
  }
  if (ball.position.z >= range || ball.position.z < -range) {
    ball.velocity.z *= -1;
  }
};

const ballMove = () => {
  const ball = gameObjects.disk;
  console.log(!ball.held);
  if (!ball.held) {
    ball.mesh.translateX(ball.velocity.x);
    ball.mesh.translateY(ball.velocity.y);
    ball.mesh.translateZ(ball.velocity.z);
    ball.position.x += ball.velocity.x;
    ball.position.y += ball.velocity.y;
    ball.position.z += ball.velocity.z;
    checkBounds(ball);
  }
  else {
    ball.mesh.position.setX(ball.currentOwner.position.x);
    ball.mesh.position.setY(ball.currentOwner.position.y);
    ball.mesh.position.setZ(-300);
    ball.position.x = ball.currentOwner.position.x;
    ball.position.y = ball.currentOwner.position.y;
    ball.position.z = -300;
  }
};

const checkGrab = (player) => {
  const ball = gameObjects.disk;
  const location = player.position;
  const ballRad = 50;
  const handRad = 50;
  const dX = ball.position.x - location.x;
  const dY = ball.position.y - location.y;
  if (Math.abs(ball.position.z - location.z) < ballRad) {
    const between = (dX * dX) + (dY * dY);

    if (between <= ballRad * ballRad + handRad * handRad) {
      return true;
    }
    else {
      return false;
    }
  }
  else return false;
};

const animate = () => {
  requestAnimationFrame(animate);
  if (!gameObjects.pOne.open && checkGrab(gameObjects.pOne)) {
    gameObjects.disk.held = true;
    gameObjects.disk.currentOwner = gameObjects.pOne;
  }
  if (!gameObjects.pTwo.open && checkGrab(gameObjects.pTwo)) {
    gameObjects.disk.held = true;
    gameObjects.disk.currentOwner = gameObjects.pTwo;
  }
  ballMove();
  tracker.position.setZ(gameObjects.disk.position.z);
  effect.render(scene, camera);
};

export const init = () => {
  // get dom context
  context = document.querySelector('#renderer');
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
  // camera.position.z = 400;

  scene = new THREE.Scene();
  buildPlayer('pOne');
  buildPlayer('pTwo');
  buildBall();

  tracker = new THREE.Mesh(trackerGeo, basicMat3);
  scene.add(tracker);
  // Renderer init
  renderer = new THREE.WebGLRenderer();
  context.appendChild(renderer.domElement);

  ghost = new THREE.PeppersGhostEffect(renderer);
  effect = ghost;
  effect.setSize(window.innerWidth, window.innerHeight);
  effect.cameraDistance = 1000;

  window.addEventListener('resize', onWindowResize, false);
  animate();
};

export default {
  init,
};
<commit_msg>Set up scoring<commit_after>import THREE from 'three';
import Pepper from '../lib/pepper';

// Three js constants
let context = {};
let camera = {};
let renderer;
let scene;
let effect;
let ghost;

const gameObjects = {
  disk: {},
  pOne: {},
  pTwo: {},
};

let tracker = {};

const torusGeo = new THREE.TorusGeometry(50, 20, 8, 8);
const sphereGeo = new THREE.SphereGeometry(50, 10, 10);
const trackerGeo = new THREE.CubeGeometry(500, 500, 2);
const basicMat = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const basicMat2 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const basicMat3 = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.2 });

const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  effect.setSize(window.innerWidth, window.innerHeight);
};

// SECTION
// PLAYER
// SECTION
const buildPlayer = (key) => {
  const current = gameObjects[key];
  const material = new THREE.MeshBasicMaterial();
  current.open = true;
  if (key === 'pOne') {
    current.mesh = new THREE.Mesh(torusGeo, basicMat);
    current.position = { x: 0, y: 0, z: -400 };
  }
  if (key === 'pTwo') {
    current.mesh = new THREE.Mesh(torusGeo, material);
    current.position = { x: 0, y: 0, z: 400 };
  }
  current.score = 0;
  scene.add(current.mesh);
  current.mesh.translateX(current.position.x);
  current.mesh.translateY(current.position.y);
  current.mesh.translateZ(current.position.z);
};

const shootBall = player => {

  const vector = new THREE.Vector3(0, 0, 1);
  vector.applyQuaternion(player.mesh.quaternion);
  vector.multiplyScalar(8);

  gameObjects.disk.velocity = vector;
  // after release
  gameObjects.disk.held = false;
  gameObjects.disk.currentOwner = null;
};

export const openHand = player => {
  if (!gameObjects[player].open) {
    gameObjects[player].open = true;
    gameObjects[player].mesh.scale.set(1, 1, 1);
    if (gameObjects.disk.held && gameObjects.disk.currentOwner === gameObjects[player]) {
      shootBall(gameObjects[player]);
    }
  }
};

export const closeHand = player => {
  if (gameObjects[player].open) {
    gameObjects[player].open = false;
    gameObjects[player].mesh.scale.set(0.4, 0.4, 0.4);
  }
};

export const updatePlayerTransform = (player, roll, yaw, pitch, handPos) => {
  const current = gameObjects[player];
  current.mesh.rotation.set(pitch, -yaw, roll);
  current.mesh.position.setX(handPos.x * 300);
  current.mesh.position.setY(handPos.y * 300 - 150);
  current.position.x = handPos.x * 300;
  current.position.y = handPos.y * 300 - 150;
};

const resetBall = () => {
  gameObjects.disk.position = { x: 0, y: 0, z: 0 };
  gameObjects.disk.mesh.position.set(0, 0, 0);
};

const scorePoint = position => {
  resetBall();
  if (position > 0) {
    gameObjects.pOne.score++;
    gameObjects.disk.velocity = { x: 0, y: 0, z: -4 };
  }
  else {
    gameObjects.pTwo.score++;
    gameObjects.disk.velocity = { x: 0, y: 0, z: 4 };
  }
};

// SECTION
// BALL
// SECTION
const buildBall = () => {
  const ball = gameObjects.disk;
  ball.mesh = new THREE.Mesh(sphereGeo, basicMat2);
  ball.position = { x: 0, y: 0, z: 0 };
  ball.velocity = { x: 0, y: 0, z: -4 };
  scene.add(ball.mesh);
  ball.held = false;
};

const checkBounds = ball => {
  const range = 360;
  if (ball.position.x >= (range - 110) || ball.position.x < -(range - 110)) {
    ball.velocity.x *= -1;
  }
  if (ball.position.y >= (range - 110) || ball.position.y < -(range - 110)) {
    ball.velocity.y *= -1;
  }
  if (ball.position.z >= range || ball.position.z < -range) {
    scorePoint(ball.position.z);
  }
};

const ballMove = () => {
  const ball = gameObjects.disk;
  console.log(!ball.held);
  if (!ball.held) {
    ball.mesh.translateX(ball.velocity.x);
    ball.mesh.translateY(ball.velocity.y);
    ball.mesh.translateZ(ball.velocity.z);
    ball.position.x += ball.velocity.x;
    ball.position.y += ball.velocity.y;
    ball.position.z += ball.velocity.z;
    checkBounds(ball);
  }
  else {
    ball.mesh.position.setX(ball.currentOwner.position.x);
    ball.mesh.position.setY(ball.currentOwner.position.y);
    ball.mesh.position.setZ(-300);
    ball.position.x = ball.currentOwner.position.x;
    ball.position.y = ball.currentOwner.position.y;
    ball.position.z = -300;
  }
};

const checkGrab = (player) => {
  const ball = gameObjects.disk;
  const location = player.position;
  const ballRad = 50;
  const handRad = 50;
  const dX = ball.position.x - location.x;
  const dY = ball.position.y - location.y;
  if (Math.abs(ball.position.z - location.z) < ballRad) {
    const between = (dX * dX) + (dY * dY);

    if (between <= ballRad * ballRad + handRad * handRad) {
      return true;
    }
    else {
      return false;
    }
  }
  else return false;
};

const animate = () => {
  requestAnimationFrame(animate);
  if (!gameObjects.pOne.open && checkGrab(gameObjects.pOne)) {
    gameObjects.disk.held = true;
    gameObjects.disk.currentOwner = gameObjects.pOne;
  }
  if (!gameObjects.pTwo.open && checkGrab(gameObjects.pTwo)) {
    gameObjects.disk.held = true;
    gameObjects.disk.currentOwner = gameObjects.pTwo;
  }
  ballMove();
  tracker.position.setZ(gameObjects.disk.position.z);
  effect.render(scene, camera);
};

export const init = () => {
  // get dom context
  context = document.querySelector('#renderer');
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
  // camera.position.z = 400;

  scene = new THREE.Scene();
  buildPlayer('pOne');
  buildPlayer('pTwo');
  buildBall();

  tracker = new THREE.Mesh(trackerGeo, basicMat3);
  scene.add(tracker);
  // Renderer init
  renderer = new THREE.WebGLRenderer();
  context.appendChild(renderer.domElement);

  ghost = new THREE.PeppersGhostEffect(renderer);
  effect = ghost;
  effect.setSize(window.innerWidth, window.innerHeight);
  effect.cameraDistance = 1000;

  window.addEventListener('resize', onWindowResize, false);
  animate();
};

export default {
  init,
};
<|endoftext|>


<commit_before>"use strict";

var U = require('util');

/* Using techniques described here:
  http://pivotallabs.com/users/pjaros/blog/articles/1368-javascript-constructors-prototypes-and-the-new-keyword
*/

// This creates an object which inherits from another object.
var create = exports.create = function(parent) {
  var F = function() {};
  F.prototype = parent;
  return new F();
};

// *********************************
// State / Stats / Config vars
// *********************************

// Statistics
var _Stats = {
    connections: {
        admin:  0,
        tcp:    0,
        udp:    0,
        socket: 0,
        file:   0,
        total:  0,
        last:   0,
        idle:   0,
        failed: 0,
    },
    // Inlined so common.js can use base.js
    start_time: Math.round( new Date().getTime() / 1000 ),
    uptime: 0,
};

// Global state
var _State = {
    // will be 'server:port' => server object (see ___remote_*_connect)
    all_servers:        { },
    // list of servers messages should be delivered to. Updated by
    // an event loop periodically
    current_servers:    [ ],
    // a list of all listeners currently open
    listeners:          { },
};

// These will be filled from the main program as needed.
var _Config = {};

// This is an optional Statsd remote, which may or may not be configured
var _Statsd = false;

exports.BaseObject = function() {
    var _obj = (function(){
        var obj = {};

        // Singletons - any change to this will be reflected in all
        // objects built on top
        obj.config_object  = function() { return _Config; };
        obj.state_object   = function() { return _State;  };
        obj.stats_object   = function() { return _Stats;  };
        obj.statsd_object  = function() { return _Statsd; };

        // provide setters in case this needs to change.
        // re-assigning the obj.config/.state doesn't appear
        // to carry accross base objects
        obj._set_state_object   = function( new_state )  { _State  = new_state;  };
        obj._set_stats_object   = function( new_stats )  { _Stats  = new_stats;  };
        obj._set_statsd_object  = function( new_statsd ) { _Statsd = new_statsd; };
        obj._set_config_object  = function( new_cfg )    { _Config = new_cfg;    };

        // Quick and dirty way to dump state/config
        obj.___dump = function() {
            U.log( "Dump: " +  U.inspect( [ _State, _Config ] ) );
        };

        return obj;
    }());
    return create( _obj );
};
<commit_msg>* add stats for health checks, so they can be sent to statsd<commit_after>"use strict";

var U = require('util');

/* Using techniques described here:
  http://pivotallabs.com/users/pjaros/blog/articles/1368-javascript-constructors-prototypes-and-the-new-keyword
*/

// This creates an object which inherits from another object.
var create = exports.create = function(parent) {
  var F = function() {};
  F.prototype = parent;
  return new F();
};

// *********************************
// State / Stats / Config vars
// *********************************

// Statistics
var _Stats = {
    connections: {
        admin:  0,
        tcp:    0,
        udp:    0,
        socket: 0,
        file:   0,
        total:  0,
        last:   0,
        idle:   0,
        failed: 0,
    },
    // Inlined so common.js can use base.js
    start_time: Math.round( new Date().getTime() / 1000 ),
    uptime: 0,
};

// Global state - Used mostly by RemotePool
var _State = {
    // will be 'server:port' => server object
    all_servers:        { },
    // list of servers messages should be delivered to. Updated by
    // an event loop periodically
    current_servers:    [ ],
    // a list of all listeners currently open
    listeners:          { },
    // State on healthy/unhealthy nodes & chains
    health_check:       {
        healthy_remotes:    0,
        unhealthy_remotes:  0,
        healthy_chains:     0,
        unhealthy_chains:   0,
    },
};

// These will be filled from the main program as needed.
var _Config = {};

// This is an optional Statsd remote, which may or may not be configured
var _Statsd = false;

exports.BaseObject = function() {
    var _obj = (function(){
        var obj = {};

        // Singletons - any change to this will be reflected in all
        // objects built on top
        obj.config_object  = function() { return _Config; };
        obj.state_object   = function() { return _State;  };
        obj.stats_object   = function() { return _Stats;  };
        obj.statsd_object  = function() { return _Statsd; };

        // provide setters in case this needs to change.
        // re-assigning the obj.config/.state doesn't appear
        // to carry accross base objects
        obj._set_state_object   = function( new_state )  { _State  = new_state;  };
        obj._set_stats_object   = function( new_stats )  { _Stats  = new_stats;  };
        obj._set_statsd_object  = function( new_statsd ) { _Statsd = new_statsd; };
        obj._set_config_object  = function( new_cfg )    { _Config = new_cfg;    };

        // Quick and dirty way to dump state/config
        obj.___dump = function() {
            U.log( "Dump: " +  U.inspect( [ _State, _Config ] ) );
        };

        return obj;
    }());
    return create( _obj );
};
<|endoftext|>


<commit_before>/**
 * The base class for all sns client
 * @author Tang Bo Hao
 */

// Module Dependence
var crypto= require('crypto'),
    http= require('http'),
    https= require('https'),
    URL= require('url'),
    zlib= require('zlib'),
    querystring = require('querystring'),
    commonAPIs = require('./apiconfig').commonAPIs;

// export class
var SocialBase = module.exports = function ClientBase(user){
};

SocialBase.prototype.get = function get(api, param, callback) {
  callback(new Error('missing implementation of get') );
};

SocialBase.prototype.post = function post(api, body, callback) {
  callback(new Error('missing implementation of post') );
};

SocialBase.prototype.filterResponse = function(direct, reqCallback, err, data) {
  if(err) return reqCallback(err);
  if(direct) return reqCallback( null, data );

  if(Array.isArray(data)){ // should be a array
    data = data.map(function(item){
        return this.geneCommonUser(item);
    }, this);
  }else{ // should be a object
    data = this.geneCommonUser(data);
  }
  reqCallback(null, data);
};

/**
 * Generate user object by server data
 * each client should have their own version
 * return {Object}
 */
SocialBase.prototype.geneCommonUser = function geneCommonUser( data ) {
  return data;
};

// ===! ===== Common SNS API ==========
// generate CommonAPIs function
var apiname, apimethod, cfg, isDirect;
for (var key in commonAPIs) {
  apiname = key;
  cfg = commonAPIs[key].split("_");
  apimethod = cfg[0];
  isDirect = cfg[1] === "direct";
  SocialBase.prototype[apiname] = (function(name, method, direct){
      return function(param, callback){
        var api = this.api[name];
        if(api)
          (this[method])(api, param, this.filterResponse.bind(this, direct, callback ) );
        else
          callback(new Error("not support api:" + name) );
      };
  })(apiname, apimethod, isDirect);
};

SocialBase.checkSignature = function(query){
  return true;
}

SocialBase.prototype.verify = function (callback) {
  callback();
}

// =====!===== Utility functions ============

SocialBase.prototype._createClient= function( port, hostname, method, path, headers, sslEnabled ) {
  var options = {
    host: hostname,
    port: port,
    path: path,
    method: method,
    headers: headers
  };
  var httpModel;
  if( sslEnabled ) {
    httpModel= https;
  } else {
    httpModel= http;
  }
  return httpModel.request(options);
};

SocialBase.prototype._performSecureRequest= function( method, url, extra_params, post_content_type,  callback ) {

  if( !post_content_type ) {
    post_content_type= "application/x-www-form-urlencoded";
  }

  var post_body = null;
  if(extra_params) {
    if( (method == "POST" || method == "PUT")  && extra_params != null ) {
      post_body= querystring.stringify(extra_params);
    } else {
      url += (url.indexOf('?') >= 0 ? '&' : '?')  + querystring.stringify(extra_params);
    }
  }

  var parsedUrl= URL.parse( url, false );
  if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
  if( parsedUrl.protocol == "https:" && !parsedUrl.port ) parsedUrl.port= 443;

  var headers= {};
  headers["Accept"]= "*/*";
  headers["Accept-Encoding"]= "gzip";
  headers["Connection"]= "close";
  headers["User-Agent"]= "Node Server";
  headers["Host"]= parsedUrl.host;
  headers["Content-Length"]= post_body ? Buffer.byteLength(post_body) : 0;
  headers["Content-Type"]= post_content_type;
  var path;
  if( !parsedUrl.pathname  || parsedUrl.pathname == "" ) parsedUrl.pathname ="/";
  if( parsedUrl.query ) path= parsedUrl.pathname + "?"+ parsedUrl.query ;
  else path= parsedUrl.pathname;
  var request;
  if( parsedUrl.protocol == "https:" ) {
    request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers, true);
  }
  else {
    request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers);
  }

  if( callback ) {
    var dataBuffer = null;
    var datastr = "";
    var self = this;

    var allowEarlyClose= true;
    var callbackCalled= false;
    function passBackControl( response ) {
      if(!callbackCalled) {
        callbackCalled= true;
        if( dataBuffer ){
          datastr = dataBuffer.toString();
        }
        if ( response.statusCode >= 200 && response.statusCode <= 299
          && datastr.indexOf('error_code') < 0 /* for wyx error_code*/) {
          callback(null, datastr, response);
        } else {
          callback({ statusCode: response.statusCode, data: datastr }, datastr, response);
        }
      }
    }

    request.on('response', function (response) {
      if (response.headers['content-encoding'] == 'gzip') {
        var gunzip = zlib.createGunzip();
        response.pipe(gunzip);
        gunzip.on('data', function (chunk) {
          dataBuffer = chunk;
        });
        gunzip.on('end', function () {
          passBackControl( response );
        });
      }else{
        if( response.headers['content-length'] ){
          dataBuffer = new Buffer(Number(response.headers['content-length']));
        }
        response.setEncoding('utf8');
        response.on('data', function (chunk) {
          if( dataBuffer ){
            dataBuffer.write(chunk);
          }else{
            datastr += chunk;
          }
        });
        response.on('end', function () {
          passBackControl( response );
        });
      }
      response.on('close', function () {
        if( allowEarlyClose ) {
          passBackControl( response );
        }
      });
    });

    request.on("error", function(err) {
        callbackCalled= true;
        callback( err )
    });

    if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
      request.write(post_body);
    }
    request.end();
  }
  else {
    if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
      request.write(post_body);
    }
    return request;
  }

  return;
};
<commit_msg>fix request bug<commit_after>/**
 * The base class for all sns client
 * @author Tang Bo Hao
 */

// Module Dependence
var crypto= require('crypto'),
    http= require('http'),
    https= require('https'),
    URL= require('url'),
    zlib= require('zlib'),
    querystring = require('querystring'),
    commonAPIs = require('./apiconfig').commonAPIs;

// export class
var SocialBase = module.exports = function ClientBase(user){
};

SocialBase.prototype.get = function get(api, param, callback) {
  callback(new Error('missing implementation of get') );
};

SocialBase.prototype.post = function post(api, body, callback) {
  callback(new Error('missing implementation of post') );
};

SocialBase.prototype.filterResponse = function(direct, reqCallback, err, data) {
  if(err) return reqCallback(err);
  if(direct) return reqCallback( null, data );

  if(Array.isArray(data)){ // should be a array
    data = data.map(function(item){
        return this.geneCommonUser(item);
    }, this);
  }else{ // should be a object
    data = this.geneCommonUser(data);
  }
  reqCallback(null, data);
};

/**
 * Generate user object by server data
 * each client should have their own version
 * return {Object}
 */
SocialBase.prototype.geneCommonUser = function geneCommonUser( data ) {
  return data;
};

// ===! ===== Common SNS API ==========
// generate CommonAPIs function
var apiname, apimethod, cfg, isDirect;
for (var key in commonAPIs) {
  apiname = key;
  cfg = commonAPIs[key].split("_");
  apimethod = cfg[0];
  isDirect = cfg[1] === "direct";
  SocialBase.prototype[apiname] = (function(name, method, direct){
      return function(param, callback){
        var api = this.api[name];
        if(api)
          (this[method])(api, param, this.filterResponse.bind(this, direct, callback ) );
        else
          callback(new Error("not support api:" + name) );
      };
  })(apiname, apimethod, isDirect);
};

SocialBase.checkSignature = function(query){
  return true;
}

SocialBase.prototype.verify = function (callback) {
  callback();
}

// =====!===== Utility functions ============

SocialBase.prototype._createClient= function( port, hostname, method, path, headers, sslEnabled ) {
  var options = {
    host: hostname,
    port: port,
    path: path,
    method: method,
    headers: headers
  };
  var httpModel;
  if( sslEnabled ) {
    httpModel= https;
  } else {
    httpModel= http;
  }
  return httpModel.request(options);
};

SocialBase.prototype._performSecureRequest= function( method, url, extra_params, post_content_type,  callback ) {

  if( !post_content_type ) {
    post_content_type= "application/x-www-form-urlencoded";
  }

  var post_body = null;
  if(extra_params) {
    if( (method == "POST" || method == "PUT")  && extra_params != null ) {
      post_body= querystring.stringify(extra_params);
    } else {
      url += (url.indexOf('?') >= 0 ? '&' : '?')  + querystring.stringify(extra_params);
    }
  }

  var parsedUrl= URL.parse( url, false );
  if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
  if( parsedUrl.protocol == "https:" && !parsedUrl.port ) parsedUrl.port= 443;

  var headers= {};
  headers["Accept"]= "*/*";
  headers["Accept-Encoding"]= "gzip";
  headers["Connection"]= "close";
  headers["User-Agent"]= "Node Server";
  headers["Host"]= parsedUrl.host;
  headers["Content-Length"]= post_body ? Buffer.byteLength(post_body) : 0;
  headers["Content-Type"]= post_content_type;
  var path;
  if( !parsedUrl.pathname  || parsedUrl.pathname == "" ) parsedUrl.pathname ="/";
  if( parsedUrl.query ) path= parsedUrl.pathname + "?"+ parsedUrl.query ;
  else path= parsedUrl.pathname;
  var request;
  if( parsedUrl.protocol == "https:" ) {
    request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers, true);
  }
  else {
    request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers);
  }

  if( callback ) {
    var self = this;

    var allowEarlyClose= true;
    var callbackCalled= false;

    function passBackControl( datastr, dataBuffers, response ) {
      if(!callbackCalled) {
        callbackCalled= true;
        if( dataBuffers ){
          datastr = Buffer.concat(dataBuffers).toString();
        }
        if ( response.statusCode >= 200 && response.statusCode <= 299 ) {
          callback(null, datastr, response);
        } else {
          callback({ statusCode: response.statusCode, data: datastr }, datastr, response);
        }
      }
    }

    var onResponse = function ( response) {
      var dataBuffers = null;
      var datastr = "";
      if( response.headers['content-length'] ){
        dataBuffers = [];
      }
      if (response.headers['content-encoding'] == 'gzip') {
        var gunzip = zlib.createGunzip();
        response.pipe(gunzip);
        gunzip.on('data', function (chunk) {
          dataBuffers.push( chunk );
        });
        gunzip.on('end', function () {
          passBackControl( null, dataBuffers, response );
        });
      }else{
        response.setEncoding('utf8');
        response.on('data', function (chunk) {
          if( dataBuffers ){
            dataBuffers.push( new Buffer(chunk) );
          }else{
            datastr += chunk;
          }
        });
        response.on('end', function () {
          passBackControl( datastr, dataBuffers, response );
        });
      }
      response.on('close', function () {
        if( allowEarlyClose ) {
          passBackControl( datastr, dataBuffers, response );
        }
      });
    }

    request.on('response', onResponse );
    request.on("error", function(err) {
        callbackCalled= true;
        callback( err )
    });

    if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
      request.write(post_body);
    }
    request.end();
  }
  else {
    if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
      request.write(post_body);
    }
    return request;
  }

  return;
};
<|endoftext|>


<commit_before>/*
 * gith
 * https://github.com/danheberden/gith
 *
 * Copyright (c) 2012 Dan Heberden
 * Licensed under the MIT license.
 */

var http = require("http");
var path = require("path");
var fs = require("fs");
var EventEmitter2 = require( "EventEmitter2" ).EventEmitter2;
var util = require("util");
var _ = require("lodash");

var Gith = function( eventaur, settings ) {
  var gith = this;
  this.settings = settings || {};

  // make this bad boy an event emitter
  EventEmitter2.call( this, {
    wildcard: true,
    delimiter: ':',
    maxListeners: 0
  });

  // handle bound payloads
  eventaur.on( 'payload', function( payload ) {
    gith.emit( 'payload', {}, payload );
  });

};

// inherit the EventEmitter2 stuff
util.inherits( Gith, EventEmitter2 );

// the listen method - this gets added/bound in
// module.exports.create, fyi
var listen = function( eventaur, port ) {
  if ( port ) {
    this.port = port;
  }
  if ( !this.port ) {
    throw new Error('.listen() requires a port to be set');
  }

  this.server = http.createServer( function( req, res ) {
    var data = "";
    if ( req.method === "POST" ) {
      req.on( "data", function( chunk ) {
        data += chunk;
      });
    }

    req.on( "end", function() {
      if ( /^payload=/.test( data ) ) {
        var payload = JSON.parse( data.slice(8) );
        eventaur.emit( "payload", payload );
      }
      res.end();
    });

    res.writeHead( 200, {
      'Content-type': 'text/html'
    });
    res.end();
  }).listen( port );
};

// make require('gith')( 9001 ) work if someone really wants to
module.exports = function( port ) {
  return module.exports.create( port );
};

// make the preferred way of `require('gith').create( 9001 ) work
module.exports.create = function( port ) {

  // make an event emitter to use for the hardcore stuff
  var eventaur = new EventEmitter2({
    wildcard: true,
    delimter: ':',
    maxListeners: 0
  });

  // return a function that
  //   a) holds its own server/port/whatever
  //   b) exposes a listen method
  //   c) is a function that returns a new Gith object
  //   d) emits global events for things like 'payload'
  var ret = function( map ) {
    // make a new Gith with a reference to this factory
    return new Gith( eventaur, map );
  };

  // add the listen method to the function - bind to ret
  // and send eventaur to it
  ret.listen = listen.bind( ret, eventaur );

  // expose ability to close http server
  ret.close = function(){
    this.server.close();
  };

  ret.payload = function( payload ) {
   eventaur.emit( 'payload', payload );
  };

  // if create was sent port, call listen automatically
  if ( port ) {
    ret.listen( port );
  }

  // return the new function
  return ret;
};
<commit_msg>Add first revision of simpler payload, filtering and event broadcasts<commit_after>/*
 * gith
 * https://github.com/danheberden/gith
 *
 * Copyright (c) 2012 Dan Heberden
 * Licensed under the MIT license.
 */

var http = require("http");
var path = require("path");
var fs = require("fs");
var EventEmitter2 = require( "EventEmitter2" ).EventEmitter2;
var util = require("util");
var _ = require("lodash");

var filterSettings = function( settings, payload ) {

  // add the matches object for later
  payload.matches = {};

  // check all the things
  var checksPassed;

  [ 'repo', 'branch', 'file' ].forEach( function( thing ) {
    var wat = settings[ thing ];

    // default to a passed state
    var passed = true;

    // was a filter specified? and is it not a wildcard?
    if ( wat && wat !== '*' ) {

      // checking, so default passed to false
      passed = false;

      // make an array of the thing or all the files
      var checks = [].concat( thing === 'file' ? payload.files.all : payload[ thing ] );

      // all the checks - did any of them pass?
      passed = checks.some( function( check ) {

         // direct match
        if ( wat === check ) {
          return true;
        }

        // if negated match (!string)
        if ( _.isString( wat ) && wat[0] === "!" &&
              wat.slice(1) !== check ) {
          return true;
        }

        // regex?
        if ( _.isRegExp( wat ) ) {
          var match = check.match( wat );

          // did it match? huh? did it?
          if ( match ) {

            // goddamn files being different
            if ( thing === 'file' ) {
              payload.matches.files[ check ] = match;
            } else {
              payload.matches[ thing ] = match;
            }

            return true;
          }
        }
      });

      // usr function?
      if ( _.isFunction( wat ) ) {
        passed = wat( payload[ thing ], payload );
      }

      // assign the final result of this 'thing' to checksPassed
      checksPassed = passed;
    }
  });

  return checksPassed;
};

var Gith = function( eventaur, settings ) {
  var gith = this;
  this.settings = settings || {};

  // make this bad boy an event emitter
  EventEmitter2.call( this, {
    wildcard: true,
    delimiter: ':',
    maxListeners: 0
  });

  // handle bound payloads
  eventaur.on( 'payload', function( originalPayload ) {

    // make a simpler payload
    var payload = gith.simplifyPayload( originalPayload );

    // bother doing anything?
    if ( filterSettings( settings, payload ) ) {

      // all the things
      gith.emit( 'all', payload );

      // did we do any branch work?
      if ( originalPayload.created && originalPayload.forced && payload.branch ) {
        gith.emit( 'branch:add', payload );
      }
      if (  originalPayload.deleted && originalPayload.forced && payload.branch ) {
        gith.emit( 'branch:delete', payload );
      }

      // how about files?
      if ( payload.files.added.length > 0 ) {
        gith.emit( 'file:add', payload );
      }
      if ( payload.files.deleted.length > 0 ) {
        gith.emit( 'file:delete', payload );
      }
      if ( payload.files.modified.length > 0 ) {
        gith.emit( 'file:modify', payload );
      }
      if ( payload.files.all.length > 0 ) {
        gith.emit( 'file:all', payload );
      }

      // tagging?
      if ( payload.tag && originalPayload.created ) {
        gith.emit( 'tag:add', payload );
      }
      if ( payload.tag && originalPayload.deleted ) {
        gith.emit( 'tag:delete', payload );
      }

    }

  });
};

// inherit the EventEmitter2 stuff
util.inherits( Gith, EventEmitter2 );

Gith.prototype.simplifyPayload = function( payload ) {
  var branch = '';
  var tag = '';

  // break out if it was a tag or branch and assign
  var refMatches = ( payload.ref || "" ).match( /refs\/(tags|heads)\/(.*)$/ );
  if ( refMatches ) {
    if ( refMatches[1] === "heads" ) {
      branch = refMatches[2];
    }
    if ( refMatches[1] === "tags" ) {
      tag = refMatches[2];
    }
  }

  var simpler = {
    original: payload,
    files: {
      all: [],
      added: [],
      deleted: [],
      modified: []
    },
    tag: tag,
    branch: branch,
    repo: payload.repository.owner.name + '/' + payload.repository.name,
    sha: payload.after,
    time: payload.repository.pushed_at,
    urls: {
      head: payload.head_commit.url,
      branch: '',
      tag: '',
      repo: payload.repository.url,
      compare: payload.compare
    },
    reset: !payload.created && payload.forced,
    pusher: payload.pusher.name,
    owner: payload.repository.owner.name
  };

  if ( branch ) {
    simpler.urls.branch = simpler.urls.branch + '/tree/' + branch;
  }
  if ( tag ) {
    simpler.urls.tag = simpler.urls.head;
  }

  // populate files for every commit
  payload.commits.forEach( function( commit ) {
    [ 'added', 'modified', 'deleted' ].forEach( function( v ) {
      simpler[ v ].concat( commit[v] );
      simpler.all.concat( commit[v] );
    });
  });

  // todo: use github api to find what files were removed if the
  // head was reset? maybe?
};

// the listen method - this gets added/bound in
// module.exports.create, fyi
var listen = function( eventaur, port ) {
  // are we changing ports?
  if ( port ) {
    this.port = port;
  }
  if ( !this.port ) {
    throw new Error('.listen() requires a port to be set');
  }

  this.server = http.createServer( function( req, res ) {
    var data = "";
    if ( req.method === "POST" ) {
      req.on( "data", function( chunk ) {
        data += chunk;
      });
    }

    req.on( "end", function() {
      if ( /^payload=/.test( data ) ) {
        var payload = JSON.parse( data.slice(8) );
        eventaur.emit( "payload", payload );
      }
      res.end();
    });

    res.writeHead( 200, {
      'Content-type': 'text/html'
    });
    res.end();
  }).listen( port );
};

// make require('gith')( 9001 ) work if someone really wants to
module.exports = function( port ) {
  return module.exports.create( port );
};

// make the preferred way of `require('gith').create( 9001 ) work
module.exports.create = function( port ) {

  // make an event emitter to use for the hardcore stuff
  var eventaur = new EventEmitter2({
    wildcard: true,
    delimter: ':',
    maxListeners: 0
  });

  // return a function that
  //   a) holds its own server/port/whatever
  //   b) exposes a listen method
  //   c) is a function that returns a new Gith object
  //   d) emits global events for things like 'payload'
  var ret = function( map ) {
    // make a new Gith with a reference to this factory
    return new Gith( eventaur, map );
  };

  // add the listen method to the function - bind to ret
  // and send eventaur to it
  ret.listen = listen.bind( ret, eventaur );

  // expose ability to close http server
  ret.close = function(){
    this.server.close();
  };

  ret.payload = function( payload ) {
   eventaur.emit( 'payload', payload );
  };

  // if create was sent port, call listen automatically
  if ( port ) {
    ret.listen( port );
  }

  // return the new function
  return ret;
};
<|endoftext|>


<commit_before>'use strict';

var util = require('util'),
    EventEmitter = require('events').EventEmitter,
    _ = require('lodash'),
    uuid = require('node-uuid').v4;

/**
 * Queue constructor
 * @param {Object} options The options can have information like host, port, etc. [optional]
 */
function Queue(options) {
  options = options || {};

  EventEmitter.call(this, options);
}

util.inherits(Queue, EventEmitter);

function implementError (callback) {
  var err = new Error('Storage method add is not implemented');
  if (callback) callback(err);
  throw err;
}

_.extend(Queue.prototype, {

  /**
   * Initiate communication with the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err, queue){}`
   */
  connect: implementError,

  /**
   * Terminate communication with the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err){}`
   */
  disconnect: implementError,

  /**
   * Use this function to obtain a new id.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, id){}` id is of type String.
   */
  getNewId: function (callback) {
    var id = uuid().toString();
    if (callback) callback(null, id);
  },

  /**
   * Use this function to push something in the queue.
   * @param  {String}   id       The id for this item.
   * @param  {Object}   item     The item, that should be pushed to the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err){}`
   */
  push: function (id, item, callback) {
    implementError(callback);
  },

  /**
   * Use this function to get get all the items from the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, items){}` items is of type Array.
   */
  getAll: implementError,

  /**
   * Use this function to check if an item with this id is already queued.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, isQueued){}` isQueued is of type Boolean.
   */
  isQueued: function (id, callback) {
    implementError(callback);
  },

  /**
   * Use this function to decrement the workers property in an item in the queue.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, hasBeenRemoved){}` hasBeenRemoved is of type Boolean. If hasBeenRemoved the item has been removed.
   */
  decrement: function (id, callback) {
    implementError(callback);
  },

  /**
   * Use this function to dequeue an item.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err){}`
   */
  remove: function (id, callback) {
    implementError(callback);
  }

});

module.exports = Queue;
<commit_msg>little optimization<commit_after>'use strict';

var util = require('util'),
    EventEmitter = require('events').EventEmitter,
    _ = require('lodash'),
    uuid = require('node-uuid').v4;

/**
 * Queue constructor
 * @param {Object} options The options can have information like host, port, etc. [optional]
 */
function Queue(options) {
  options = options || {};

  EventEmitter.call(this);
}

util.inherits(Queue, EventEmitter);

function implementError (callback) {
  var err = new Error('Storage method add is not implemented');
  if (callback) callback(err);
  throw err;
}

_.extend(Queue.prototype, {

  /**
   * Initiate communication with the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err, queue){}`
   */
  connect: implementError,

  /**
   * Terminate communication with the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err){}`
   */
  disconnect: implementError,

  /**
   * Use this function to obtain a new id.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, id){}` id is of type String.
   */
  getNewId: function (callback) {
    var id = uuid().toString();
    if (callback) callback(null, id);
  },

  /**
   * Use this function to push something in the queue.
   * @param  {String}   id       The id for this item.
   * @param  {Object}   item     The item, that should be pushed to the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed. [optional]
   *                             `function(err){}`
   */
  push: function (id, item, callback) {
    implementError(callback);
  },

  /**
   * Use this function to get get all the items from the queue.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, items){}` items is of type Array.
   */
  getAll: implementError,

  /**
   * Use this function to check if an item with this id is already queued.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, isQueued){}` isQueued is of type Boolean.
   */
  isQueued: function (id, callback) {
    implementError(callback);
  },

  /**
   * Use this function to decrement the workers property in an item in the queue.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err, hasBeenRemoved){}` hasBeenRemoved is of type Boolean. If hasBeenRemoved the item has been removed.
   */
  decrement: function (id, callback) {
    implementError(callback);
  },

  /**
   * Use this function to dequeue an item.
   * @param  {String}   id       The id for that item.
   * @param  {Function} callback The function, that will be called when the this action is completed.
   *                             `function(err){}`
   */
  remove: function (id, callback) {
    implementError(callback);
  }

});

module.exports = Queue;
<|endoftext|>


<commit_before>var _ = require('underscore');

// Glue is an object listener library for javascript.
//
// For example, the value of 'v1' of hash:
// {v1: 'value'}
//
// Can be observe with key:
// "v1"
//
// Objects can be arbitrarily complex. For example, one can observe 'value'
// within this structure:
//
// {v1: arr1: [{v2: v3: arr2: ['value']}]}
//
// with the key:
// 'v1.arr1[0].v2.v3.arr2[0]'
//
// Similarly one can observe an arbitrary element of arr2 with the key:
// 'v1.arr1[0].v2.v3.arr2[]'
//
// And of course one can observe the array itself with the key:
// 'v1.arr1[0].v2.v3.arr'
//
// Possible values for key:
// '*':               any key
// 'v1':              target: {v1: 'foo'}
// 'v1.v2':           target: {v1: {v2: {...}}
// '[]':              target: []
// 'arr':             target: {arr: []}                 * the array itself
// 'arr[]':           target: {arr: []}                 * targets the elements of the array
// 'v1.arr:           target: {v1: {arr: []}}
// 'arr[i].v1.arr     target: {arr: [{v1: arr: []}]}
// 'arr[i].v1.arr[]   target: {arr: [{v1: arr: []}]}
//
// And any other permutations of the combinations describe
// above nested n layers deep (ex. 'v1.v2.v3.arr[i].v4 ...)

var Glue = function(target) {
  this._keys = undefined;
  this.target = target;

  this.resetListeners = function() {
    this.listeners = { any: [], assigned: {}, computed: {} };
  }

  this.resetListeners();
};

Glue.version = '0.4.3'

Glue.events = {};

// Usage:
// glue.addListener([key(s):operation(s)], [context], listener)

Glue.prototype.addListener = function() {
  var self = this,
      a    = arguments;

  if (a.length === 1) {
    add('*', a[0], this.target);
  } else if (a.length === 2) {
    _.isString(a[0]) ?  add(a[0], a[1], this.target) : add('*', a[1], a[0]);
  } else {
    add(a[0], a[2], a[1]);
  }

  function add(keysAndOperations, listener, context) {
    keysAndOperations = keysAndOperations.replace(/\s/g, '').split(':');

    var keys       = keysAndOperations[0] || '*',
        operations = keysAndOperations[1];

    _.each(keys.split(','), function(key) {
      var l = {listener: listener};

      if (operations) l.operations = operations.split(',');
      if (context) l.context = context;

      if (key === '*') {
        self.listeners.any.push(l);
      } else {
        var type = 'assigned';

        if (key.match(/\#/)) {
          type = 'computed';
          l.oldValue = self.get(key);
        }

        self.listeners[type][key] = self.listeners[type][key] || [];
        self.listeners[type][key].push(l);
      }
    });
  }
};

// Usage:
// glue.removeListener((key(s):operation(s)), [context]);

Glue.prototype.removeListener = function() {
  var self = this,
      a    = arguments;

  if(a.length === 0) {
    normalize('*');
  } else if (a.length === 1) {
    _.isString(a[0]) ? normalize(a[0]) : normalize('*', a[0]);
  } else if (a.length === 2) {
    normalize(a[0], a[1]);
  }

  function normalize(keysAndOperations, context) {
    keysAndOperations = keysAndOperations.replace(/\s/g,'').split(':');

    var keys       = keysAndOperations[0],
        operations = keysAndOperations[1];

    if (keys) {
      _.each(keys.replace(/\s/g, '').split(','), function(key) {
        remove(key, operations, context);
      });
    } else {
      remove(keys, operations, context);
    }
  };

  function remove(key, operations, context) {
    if (operations) operations = operations.split(',');

    if (key === '*') {
      self.listeners.any = rejectListeners(self.listeners.any);

      _(['assigned', 'computed']).each(function(type) {
        _.each(self.listeners[type], function(listeners, key) {
          self.listeners[type][key] = rejectListeners(listeners);
          removeIfEmpty(self.listeners[type], key);
        });
      });
    } else {
      var type = key && key.match(/\#/) ? "computed" : "assigned";

      self.listeners[type][key] = rejectListeners(self.listeners[type][key]);
      removeIfEmpty(self.listeners[type], key);
    }

    function removeIfEmpty(listeners, key) {
      if (_.isEmpty(listeners[key])) delete listeners[key];
    }

    function rejectListeners(listeners) {
      listeners = _.reject(listeners, function(listener) {
        var hasOperation = !_.isEmpty(operations);

        if (hasOperation && context) {
          if(!_.isEmpty(listener.operations)) {
            listener.operations = _.difference(listener.operations, operations);
            return _.isEmpty(listener.operations) && listener.context === context;
          }
        } else if (context) {
          return listener.context === context;
        } else if (hasOperation) {
          if(!_.isEmpty(listener.operations)) {
            listener.operations = _.difference(listener.operations, operations);
            return _.isEmpty(listener.operations);
          }
        } else {
          return true;
        }
      });

      return listeners;
    };
  };
};

// Not in the public API.
//
// Usage:
// glue.notify(key, message);

Glue.prototype.notify = function(key, msg, opts) {
};

// Usage:
// glue.setTarget(target);

Glue.prototype.setTarget = function(target){
};

// Not in the public API. It is more performant to access
// values directly through glue.target. However, one should never
// modify the values of a target object obtain directly from
// glue.target.
//
// Usage:
// glue.get(key);

Glue.prototype.get = function(key) {
  key = key.replace(/\s/g,'').replace('#','.');

  if (key.length > 0) {
    key = (_.isArray(this.target) ? "this.target" : "this.target.") + key;
  } else {
    key = "this.target";
  }

  // I know eval is generally evil, but I think it's acceptable
  // for this use case.
  return eval(key);
};

// Usage:
// glue.set(key, value);

Glue.prototype.set = function(keys, value) {
};

// Usage
// glue.remove([key]);

Glue.prototype.remove = function(keys){
};

// Usage
// topic.push([key], value);

Glue.prototype.push = function() {
};

// Usage
// glue.pop([key]);

Glue.prototype.pop = function(){
};

// Usage
// glue.filter([key], handler);

Glue.prototype.filter = function() {
};

// Usage
// glue.sort([key], handler);

Glue.prototype.sort = function() {
};

module.exports = Glue;
<commit_msg>Classify operations in Scalar/Collection<commit_after>var _ = require('underscore');

// Glue is an object listener library for javascript.
//
// For example, the value of 'v1' of hash:
// {v1: 'value'}
//
// Can be observe with key:
// "v1"
//
// Objects can be arbitrarily complex. For example, one can observe 'value'
// within this structure:
//
// {v1: arr1: [{v2: v3: arr2: ['value']}]}
//
// with the key:
// 'v1.arr1[0].v2.v3.arr2[0]'
//
// Similarly one can observe an arbitrary element of arr2 with the key:
// 'v1.arr1[0].v2.v3.arr2[]'
//
// And of course one can observe the array itself with the key:
// 'v1.arr1[0].v2.v3.arr'
//
// Possible values for key:
// '*':               any key
// 'v1':              target: {v1: 'foo'}
// 'v1.v2':           target: {v1: {v2: {...}}
// '[]':              target: []
// 'arr':             target: {arr: []}                 * the array itself
// 'arr[]':           target: {arr: []}                 * targets the elements of the array
// 'v1.arr:           target: {v1: {arr: []}}
// 'arr[i].v1.arr     target: {arr: [{v1: arr: []}]}
// 'arr[i].v1.arr[]   target: {arr: [{v1: arr: []}]}
//
// And any other permutations of the combinations describe
// above nested n layers deep (ex. 'v1.v2.v3.arr[i].v4 ...)

var Glue = function(target) {
  this._keys = undefined;
  this.target = target;

  this.resetListeners = function() {
    this.listeners = { any: [], assigned: {}, computed: {} };
  }

  this.resetListeners();
};

Glue.version = '0.4.3'

Glue.events = {};

// Usage:
// glue.addListener([key(s):operation(s)], [context], listener)

Glue.prototype.addListener = function() {
  var self = this,
      a    = arguments;

  if (a.length === 1) {
    add('*', a[0], this.target);
  } else if (a.length === 2) {
    _.isString(a[0]) ?  add(a[0], a[1], this.target) : add('*', a[1], a[0]);
  } else {
    add(a[0], a[2], a[1]);
  }

  function add(keysAndOperations, listener, context) {
    keysAndOperations = keysAndOperations.replace(/\s/g, '').split(':');

    var keys       = keysAndOperations[0] || '*',
        operations = keysAndOperations[1];

    _.each(keys.split(','), function(key) {
      var l = {listener: listener};

      if (operations) l.operations = operations.split(',');
      if (context) l.context = context;

      if (key === '*') {
        self.listeners.any.push(l);
      } else {
        var type = 'assigned';

        if (key.match(/\#/)) {
          type = 'computed';
          l.oldValue = self.get(key);
        }

        self.listeners[type][key] = self.listeners[type][key] || [];
        self.listeners[type][key].push(l);
      }
    });
  }
};

// Usage:
// glue.removeListener((key(s):operation(s)), [context]);

Glue.prototype.removeListener = function() {
  var self = this,
      a    = arguments;

  if(a.length === 0) {
    normalize('*');
  } else if (a.length === 1) {
    _.isString(a[0]) ? normalize(a[0]) : normalize('*', a[0]);
  } else if (a.length === 2) {
    normalize(a[0], a[1]);
  }

  function normalize(keysAndOperations, context) {
    keysAndOperations = keysAndOperations.replace(/\s/g,'').split(':');

    var keys       = keysAndOperations[0],
        operations = keysAndOperations[1];

    if (keys) {
      _.each(keys.replace(/\s/g, '').split(','), function(key) {
        remove(key, operations, context);
      });
    } else {
      remove(keys, operations, context);
    }
  };

  function remove(key, operations, context) {
    if (operations) operations = operations.split(',');

    if (key === '*') {
      self.listeners.any = rejectListeners(self.listeners.any);

      _(['assigned', 'computed']).each(function(type) {
        _.each(self.listeners[type], function(listeners, key) {
          self.listeners[type][key] = rejectListeners(listeners);
          removeIfEmpty(self.listeners[type], key);
        });
      });
    } else {
      var type = key && key.match(/\#/) ? "computed" : "assigned";

      self.listeners[type][key] = rejectListeners(self.listeners[type][key]);
      removeIfEmpty(self.listeners[type], key);
    }

    function removeIfEmpty(listeners, key) {
      if (_.isEmpty(listeners[key])) delete listeners[key];
    }

    function rejectListeners(listeners) {
      listeners = _.reject(listeners, function(listener) {
        var hasOperation = !_.isEmpty(operations);

        if (hasOperation && context) {
          if(!_.isEmpty(listener.operations)) {
            listener.operations = _.difference(listener.operations, operations);
            return _.isEmpty(listener.operations) && listener.context === context;
          }
        } else if (context) {
          return listener.context === context;
        } else if (hasOperation) {
          if(!_.isEmpty(listener.operations)) {
            listener.operations = _.difference(listener.operations, operations);
            return _.isEmpty(listener.operations);
          }
        } else {
          return true;
        }
      });

      return listeners;
    };
  };
};

// Not in the public API.
//
// Usage:
// glue.notify(key, operation, changes);

Glue.prototype.notify = function(key, operation, changes) {
  if (key.match(/\]$/)) {
  } else {
  }

  function execute(listener, context, messsage) {
  }
};

// Usage:
// glue.setTarget(target);

Glue.prototype.setTarget = function(target){
};

// Type: Collection
//
// Usage
// topic.push([key], value);

Glue.prototype.push = function() {
};

// Type: Collection
//
// Usage
// glue.pop([key]);

Glue.prototype.pop = function(){
};

// Type: Collection
//
// Usage
// glue.insert([key], index, value);

Glue.prototype.insert = function(){
};

// Type: Collection
//
// Usage
// glue.filter([key], handler);

Glue.prototype.filter = function() {
};

// Type: Collection
//
// Usage
// glue.sort([key], handler);

Glue.prototype.sort = function() {
};

// Type: Scalar/Collection
//
// Not in the public API. It is more performant to access
// values directly through glue.target. However, one should never
// modify the values of a target object obtain directly from
// glue.target.
//
// Usage:
// glue.get(key);

Glue.prototype.get = function(key) {
  key = key.replace(/\s/g,'').replace('#','.');

  if (key.length > 0) {
    key = (_.isArray(this.target) ? "this.target" : "this.target.") + key;
  } else {
    key = "this.target";
  }

  // I know eval is generally evil, but I think it's acceptable
  // for this use case.
  return eval(key);
};

// Type: Scalar/Collection
//
// Usage:
// glue.set(key, value);

Glue.prototype.set = function(keys, value) {
};

// Type: Scalar/Collection
//
// Usage
// glue.remove([key]);

Glue.prototype.remove = function(keys){
};

// Type: Scalar/Collection
//
// Usage
// glue.sort(origin, destination);

Glue.prototype.swap = function() {
};

module.exports = Glue;
<|endoftext|>


<commit_before>/* eslint no-var: "off" */
var configuration = {
  extends: ['eslint:recommended'],
  env: {
    node: true,
    browser: true,
    es6: true
  },
  rules: {
    'arrow-parens': 'error',
    indent: ['error', 2, { SwitchCase: 1 }],
    'arrow-spacing': ['error', { before: true, after: true }],
    'brace-style': ['error', 'stroustrup'],
    quotes: ['error', 'single'],
    semi: ['error', 'always'],
    'newline-per-chained-call': ['error', { ignoreChainWithDepth: 2 }],
    'no-console': ['off'],
    'no-var': 'error',
    'prefer-template': 'error',
    'no-useless-concat': 'error',
    'space-before-function-paren': ['error', 'never'],
    'object-curly-spacing': ['error', 'always'],
    'array-bracket-spacing': ['error', 'never'],
    'comma-spacing': ['error', { before: false, after: true }],
    'space-infix-ops': 'error',
    'space-unary-ops': ['error', { words: true, nonwords: false }],
    'space-in-parens': ['error', 'never'],
    'keyword-spacing': 'error',
    'no-unused-vars': [
      'warn',
      {
        args: 'none',
        vars: 'all',
        varsIgnorePattern: 'React'
      }
    ],
    'default-case': 'error'
  },
  plugins: []
};

try {
  // Check if 'eslint-plugin-wyze' is installed
  require('eslint-plugin-wyze');
  configuration.plugins.push('wyze');
  configuration.rules['wyze/sort-destructuring-keys'] = [
    'error',
    'asc',
    {
      caseSensitive: false
    }
  ];
  configuration.rules['wyze/sort-imports'] = [
    'error',
    {
      ignoreCase: true,
      ignoreMemberSort: false,
      memberSyntaxSortOrder: ['default', 'named', 'all', 'type', 'none']
    }
  ];
}
catch (_) {
  // Nothing to do here.
}

module.exports = configuration;
<commit_msg>Need break a line and indent at each chained call<commit_after>/* eslint no-var: "off" */
var configuration = {
  extends: ['eslint:recommended'],
  env: {
    node: true,
    browser: true,
    es6: true
  },
  rules: {
    'arrow-parens': 'error',
    indent: ['error', 2, { SwitchCase: 1 }],
    'arrow-spacing': ['error', { before: true, after: true }],
    'brace-style': ['error', 'stroustrup'],
    quotes: ['error', 'single'],
    semi: ['error', 'always'],
    'newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }],
    'no-console': ['off'],
    'no-var': 'error',
    'prefer-template': 'error',
    'no-useless-concat': 'error',
    'space-before-function-paren': ['error', 'never'],
    'object-curly-spacing': ['error', 'always'],
    'array-bracket-spacing': ['error', 'never'],
    'comma-spacing': ['error', { before: false, after: true }],
    'space-infix-ops': 'error',
    'space-unary-ops': ['error', { words: true, nonwords: false }],
    'space-in-parens': ['error', 'never'],
    'keyword-spacing': 'error',
    'no-unused-vars': [
      'warn',
      {
        args: 'none',
        vars: 'all',
        varsIgnorePattern: 'React'
      }
    ],
    'default-case': 'error'
  },
  plugins: []
};

try {
  // Check if 'eslint-plugin-wyze' is installed
  require('eslint-plugin-wyze');
  configuration.plugins.push('wyze');
  configuration.rules['wyze/sort-destructuring-keys'] = [
    'error',
    'asc',
    {
      caseSensitive: false
    }
  ];
  configuration.rules['wyze/sort-imports'] = [
    'error',
    {
      ignoreCase: true,
      ignoreMemberSort: false,
      memberSyntaxSortOrder: ['default', 'named', 'all', 'type', 'none']
    }
  ];
}
catch (_) {
  // Nothing to do here.
}

module.exports = configuration;
<|endoftext|>


<commit_before><commit_msg>set up entry.js with old code. will modify as needed<commit_after>'use strict';

// build sass
require('./scss/main.scss');

// require node modules
const path = require('path');

// require npm modules
const angular = require('angular');
const camelcase = require('camelcase');
const pascalcase = require('pascalcase');

// require angualr modules
const ngTouch = require('angular-touch');
const ngAnimate = require('angular-animate');
const uiRouter = require('angular-ui-router');
const uiBootstrap = require('angular-ui-bootstrap');
const ngFileUpload = require('ng-file-upload');

// create angular module
const app = angular.module(camelcase(__TITLE__), [ngTouch, ngAnimate, uiRouter, uiBootstrap, ngFileUpload]);

// set up $rootScope globals
app.run(['$rootScope', function($rootScope){
  $rootScope.title = __TITLE__;
}]);

// load configuration
let context = require.context('./config/', true, /.js$/);
context.keys().forEach( path => {
  app.config(context(path));
});

// load services
context = require.context('./service/', true, /.js$/);
context.keys().forEach( key => {
  let name = camelcase(path.basename(key, '.js'));
  let module = context(key);
  app.service(name, module);
});

// load view controllers
context = require.context('./view/', true, /.js$/);
context.keys().forEach( key => {
  let name = pascalcase(path.basename(key, '.js'));
  let module = context(key);
  app.controller(name, module);
});

// load components
context = require.context('./component/', true, /.js$/);
context.keys().forEach( key => {
  let name = camelcase(path.basename(key, '.js'));
  let module = context(key);
  app.component(name, module);
});

// load directives
context = require.context('./directive/', true, /.js$/);
context.keys().forEach( key => {
  let name = camelcase(path.basename(key, '.js'));
  let module = context(key);
  app.directive(name, module);
});

// load filters
context = require.context('./filter/', true, /.js$/);
context.keys().forEach( key => {
  let name = camelcase(path.basename(key, '.js'));
  let module = context(key);
  app.filter(name, module);
});

// after everything is loaded in to the app
// load bootstrap onto the page
angular.bootstrap(document, [camelcase(__TITLE__)]);
<|endoftext|>


<commit_before>'use strict';

var BaseMethods = require('base-methods');

/**
 * Inherit `Base`. This class is used to provide baseline
 * methods for all classes on the templates API.
 *
 * ```js
 * function App() {
 *   Base.call(this);
 * }
 * Base.extend(App);
 * ```
 */

function Base() {
  BaseMethods.apply(this, arguments);
  this.use(require('base-plugins')());
  this.use(require('base-options')());
}

/**
 * Inherit `BaseMethods`
 */

BaseMethods.extend(Base);

/**
 * Expose `Base`
 */

module.exports = Base;
<commit_msg>update to use `base` instead of base-methods<commit_after>'use strict';

var Base = require('base');

/**
 * Expose `TemplatesBase`
 */

module.exports = TemplatesBase;

/**
 * Inherit `Base`. This class is used to provide baseline
 * methods for all classes on the templates API.
 *
 * ```js
 * function App() {
 *   Base.call(this);
 * }
 * Base.extend(App);
 * ```
 */

function TemplatesBase() {
  Base.apply(this, arguments);
  this.use(require('base-plugins')());
  this.use(require('base-options')());
}

/**
 * Inherit `Base`
 */

Base.extend(TemplatesBase);
<|endoftext|>