<commit_before>
lychee.define('Renderer').tags({
	platform: 'html'
}).requires([
	'lychee.Font'
]).supports(function(lychee, global) {

	if (
		typeof global.document !== 'undefined'
		&& typeof global.document.createElement === 'function'
		&& typeof global.CanvasRenderingContext2D === 'function'
	) {

		var canvas = global.document.createElement('canvas');
		if (typeof canvas.getContext === 'function') {
			return true;
		}

	}

	return false;

}).exports(function(lychee, global) {

	var Class = function(id) {

		id = typeof id === 'string' ? id : null;

		this.__id = id;
		this.__canvas = global.document.createElement('canvas');
		this.__ctx = this.__canvas.getContext('2d');

		this.__environment = {
			width: null,
			height: null,
			screen: {},
			offset: {}
		};

		this.__state = null;
		this.__alpha = 1;
		this.__background = null;
		this.__width = 0;
		this.__height = 0;

		// required for requestAnimationFrame
		this.context = this.__canvas;

		if (this.__id !== null) {
			this.__canvas.id = this.__id;
		}

		if (!this.__canvas.parentNode) {
			global.document.body.appendChild(this.__canvas);
		}

	};

	Class.prototype = {

		/*
		 * State and Environment Management
		 */

		reset: function(width, height, resetCache) {

			width = typeof width === 'number' ? width : this.__width;
			height = typeof height === 'number' ? height : this.__height;
			resetCache = resetCache === true ? true : false;

			if (resetCache === true) {
				this.__cache = {};
			}

			this.__width = width;
			this.__height = height;

			this.__canvas.width = width;
			this.__canvas.height = height;

			this.__canvas.style.width = width + 'px';
			this.__canvas.style.height = height + 'px';

			this.__updateEnvironment();

		},

		start: function() {
			if (this.__state !== 'running') {
				this.__state = 'running';
			}
		},

		stop: function() {
			this.__state = 'stopped';
		},

		clear: function() {

			if (this.__state !== 'running') return;

			// Some mobile devices have weird issues on rotations with clearRect()
			// Seems to be if the renderbuffer got bigger after rotation
			// this.__ctx.clearRect(0, 0, this.__canvas.width, this.__canvas.height);

			// fillRect() renders correctly
			this.__ctx.fillStyle = this.__background;
			this.__ctx.fillRect(0, 0, this.__canvas.width, this.__canvas.height);

		},

		flush: function() {

		},

		isRunning: function() {
			return this.__state === 'running';
		},

		getEnvironment: function() {
			this.__updateEnvironment();
			return this.__environment;
		},

		/*
		 * PRIVATE API: Helpers
		 */

		__updateEnvironment: function() {

			this.__environment.screen.width = global.innerWidth;
			this.__environment.screen.height = global.innerHeight;

			this.__environment.offset.x = this.__canvas.offsetLeft;
			this.__environment.offset.y = this.__canvas.offsetTop;

			this.__environment.width = this.__width;
			this.__environment.height = this.__height;

		},

		/*
		 * Setters
		 */

		setAlpha: function(alpha) {

			alpha = typeof alpha === 'number' ? alpha : null;

			if (alpha !== null && alpha >= 0 && alpha <= 1) {
				this.__ctx.globalAlpha = alpha;
			}

		},

		setBackground: function(color) {

			color = typeof color === 'string' ? color : '#000';

			this.__background = color;
			this.__canvas.style.backgroundColor = color;

		},

		/*
		 * Drawing API
		 */

		drawBox: function(x1, y1, x2, y2, color, background, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			background = background === true ? true : false;
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			if (background === false) {
				this.__ctx.lineWidth = lineWidth;
				this.__ctx.strokeStyle = color;
				this.__ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
			} else {
				this.__ctx.fillStyle = color;
				this.__ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
			}

		},

		drawCircle: function(x, y, radius, color, background, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			background = background === true ? true : false;
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			this.__ctx.beginPath();

			this.__ctx.arc(
				x,
				y,
				radius,
				0,
				Math.PI * 2
			);

			if (background === false) {
				this.__ctx.lineWidth = lineWidth;
				this.__ctx.strokeStyle = color;
				this.__ctx.stroke();
			} else {
				this.__ctx.fillStyle = color;
				this.__ctx.fill();
			}

			this.__ctx.closePath();

		},

		drawLine: function(x1, y1, x2, y2, color, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			this.__ctx.beginPath();

			this.__ctx.moveTo(x1, y1);
			this.__ctx.lineTo(x2, y2);

			this.__ctx.lineWidth = lineWidth;
			this.__ctx.strokeStyle = color;
			this.__ctx.stroke();

			this.__ctx.closePath();

		},

		drawSprite: function(x1, y1, sprite, map) {

			if (this.__state !== 'running') return;

			map = Object.prototype.toString.call(map) === '[object Object]' ? map : null;

			if (map === null) {

				this.__ctx.drawImage(sprite, x1, y1);

			} else {

				if (lychee.debug === true) {

					this.drawBox(
						x1,
						y1,
						x1 + map.w,
						y1 + map.h,
						'#f00',
						false,
						1
					);

				}

				this.__ctx.drawImage(
					sprite,
					map.x,
					map.y,
					map.w,
					map.h,
					x1,
					y1,
					map.w,
					map.h
				);

			}

		},

		drawText: function(x1, y1, text, font) {

			if (this.__state !== 'running') return;

			var t, l;

			// sprite based rendering
			if (font instanceof lychee.Font) {

				var settings = font.getSettings();
				var sprite = font.getSprite();

				var chr;

				// Measure text if we have to center it later
				if (x1 === 'center' || y1 === 'center') {

					var width = 0,
						height = 0;

					for (t = 0, l = text.length; t < l; t++)  {
						chr = font.get(text[t]);
						width += chr.real + settings.kerning;
						height = Math.max(height, chr.height);
					}

					if (x1 === 'center') {
						x1 = (this.__width / 2) - (width / 2);
					}

					if (y1 === 'center') {
						y1 = (this.__height / 2) - (height / 2);
					}

				}

				var margin = 0;

				for (t = 0, l = text.length; t < l; t++) {

					var chr = font.get(text[t]);

					if (lychee.debug === true) {

						this.drawBox(
							x1 + margin,
							y1,
							x1 + margin + chr.real,
							y1 + chr.height,
							'#ff0',
							false,
							1
						);

					}

					this.__ctx.drawImage(
						chr.sprite || sprite,
						chr.x,
						chr.y,
						chr.width,
						chr.height,
						x1 + margin - settings.spacing,
						y1 + settings.baseline,
						chr.width,
						chr.height
					);

					margin += chr.real + settings.kerning;

				}

			// text based rendering
			} else if (Object.prototype.toString.call(font) === '[object Object]'){

				font.color = typeof font.color === 'string' ? font.color : '#000';
				font.font = typeof font.font === 'string' ? font.font : 'Arial';
				font.size = typeof font.size === 'number' ? font.size : 12;

				if (x1 === 'center' || y1 === 'center') {

					var width = 0;
					for (t = 0, l = text.length; t < l; t++) {
						var m = this.__ctx.measureText(text[t]);
						width += m.charWidth;
					}

					if (x1 === 'center') {
						x1 = (this.__width / 2) - (width / 2);
					}

					if (y1 === 'center') {
						y1 = (this.__height / 2) - (data.size / 2);
					}

				}

				this.__ctx.font = font.size + 'px "' + font.font + '"';
				this.__ctx.fillStyle = font.color;
				this.__ctx.fillText(text, x1, y1);

			}

		}

	};

	return Class;

});

<commit_msg>lychee.Renderer: Bugfix for Safari Mobile (wherein the CanvasRenderingContext2D is an object, not a function). Thanks to @Spielmeister for debugging help<commit_after>
lychee.define('Renderer').tags({
	platform: 'html'
}).requires([
	'lychee.Font'
]).supports(function(lychee, global) {

	/*
	 * Hint for check against undefined:
	 *
	 * typeof CanvasRenderingContext2D is:
	 * > function in Chrome, Firefox, IE10
	 * > object in Safari, Safari Mobile
	 *
	 */

	if (
		typeof global.document !== 'undefined'
		&& typeof global.document.createElement === 'function'
		&& typeof global.CanvasRenderingContext2D !== 'undefined'
	) {

		var canvas = global.document.createElement('canvas');
		if (typeof canvas.getContext === 'function') {
			return true;
		}

	}

	return false;

}).exports(function(lychee, global) {

	var Class = function(id) {

		id = typeof id === 'string' ? id : null;

		this.__id = id;
		this.__canvas = global.document.createElement('canvas');
		this.__ctx = this.__canvas.getContext('2d');

		this.__environment = {
			width: null,
			height: null,
			screen: {},
			offset: {}
		};

		this.__state = null;
		this.__alpha = 1;
		this.__background = null;
		this.__width = 0;
		this.__height = 0;

		// required for requestAnimationFrame
		this.context = this.__canvas;

		if (this.__id !== null) {
			this.__canvas.id = this.__id;
		}

		if (!this.__canvas.parentNode) {
			global.document.body.appendChild(this.__canvas);
		}

	};

	Class.prototype = {

		/*
		 * State and Environment Management
		 */

		reset: function(width, height, resetCache) {

			width = typeof width === 'number' ? width : this.__width;
			height = typeof height === 'number' ? height : this.__height;
			resetCache = resetCache === true ? true : false;

			if (resetCache === true) {
				this.__cache = {};
			}

			this.__width = width;
			this.__height = height;

			this.__canvas.width = width;
			this.__canvas.height = height;

			this.__canvas.style.width = width + 'px';
			this.__canvas.style.height = height + 'px';

			this.__updateEnvironment();

		},

		start: function() {
			if (this.__state !== 'running') {
				this.__state = 'running';
			}
		},

		stop: function() {
			this.__state = 'stopped';
		},

		clear: function() {

			if (this.__state !== 'running') return;

			// Some mobile devices have weird issues on rotations with clearRect()
			// Seems to be if the renderbuffer got bigger after rotation
			// this.__ctx.clearRect(0, 0, this.__canvas.width, this.__canvas.height);

			// fillRect() renders correctly
			this.__ctx.fillStyle = this.__background;
			this.__ctx.fillRect(0, 0, this.__canvas.width, this.__canvas.height);

		},

		flush: function() {

		},

		isRunning: function() {
			return this.__state === 'running';
		},

		getEnvironment: function() {
			this.__updateEnvironment();
			return this.__environment;
		},

		/*
		 * PRIVATE API: Helpers
		 */

		__updateEnvironment: function() {

			this.__environment.screen.width = global.innerWidth;
			this.__environment.screen.height = global.innerHeight;

			this.__environment.offset.x = this.__canvas.offsetLeft;
			this.__environment.offset.y = this.__canvas.offsetTop;

			this.__environment.width = this.__width;
			this.__environment.height = this.__height;

		},

		/*
		 * Setters
		 */

		setAlpha: function(alpha) {

			alpha = typeof alpha === 'number' ? alpha : null;

			if (alpha !== null && alpha >= 0 && alpha <= 1) {
				this.__ctx.globalAlpha = alpha;
			}

		},

		setBackground: function(color) {

			color = typeof color === 'string' ? color : '#000';

			this.__background = color;
			this.__canvas.style.backgroundColor = color;

		},

		/*
		 * Drawing API
		 */

		drawBox: function(x1, y1, x2, y2, color, background, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			background = background === true ? true : false;
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			if (background === false) {
				this.__ctx.lineWidth = lineWidth;
				this.__ctx.strokeStyle = color;
				this.__ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
			} else {
				this.__ctx.fillStyle = color;
				this.__ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
			}

		},

		drawCircle: function(x, y, radius, color, background, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			background = background === true ? true : false;
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			this.__ctx.beginPath();

			this.__ctx.arc(
				x,
				y,
				radius,
				0,
				Math.PI * 2
			);

			if (background === false) {
				this.__ctx.lineWidth = lineWidth;
				this.__ctx.strokeStyle = color;
				this.__ctx.stroke();
			} else {
				this.__ctx.fillStyle = color;
				this.__ctx.fill();
			}

			this.__ctx.closePath();

		},

		drawLine: function(x1, y1, x2, y2, color, lineWidth) {

			if (this.__state !== 'running') return;

			color = typeof color === 'string' ? color : '#000';
			lineWidth = typeof lineWidth === 'number' ? lineWidth : 1;

			this.__ctx.beginPath();

			this.__ctx.moveTo(x1, y1);
			this.__ctx.lineTo(x2, y2);

			this.__ctx.lineWidth = lineWidth;
			this.__ctx.strokeStyle = color;
			this.__ctx.stroke();

			this.__ctx.closePath();

		},

		drawSprite: function(x1, y1, sprite, map) {

			if (this.__state !== 'running') return;

			map = Object.prototype.toString.call(map) === '[object Object]' ? map : null;

			if (map === null) {

				this.__ctx.drawImage(sprite, x1, y1);

			} else {

				if (lychee.debug === true) {

					this.drawBox(
						x1,
						y1,
						x1 + map.w,
						y1 + map.h,
						'#f00',
						false,
						1
					);

				}

				this.__ctx.drawImage(
					sprite,
					map.x,
					map.y,
					map.w,
					map.h,
					x1,
					y1,
					map.w,
					map.h
				);

			}

		},

		drawText: function(x1, y1, text, font) {

			if (this.__state !== 'running') return;

			var t, l;

			// sprite based rendering
			if (font instanceof lychee.Font) {

				var settings = font.getSettings();
				var sprite = font.getSprite();

				var chr;

				// Measure text if we have to center it later
				if (x1 === 'center' || y1 === 'center') {

					var width = 0,
						height = 0;

					for (t = 0, l = text.length; t < l; t++)  {
						chr = font.get(text[t]);
						width += chr.real + settings.kerning;
						height = Math.max(height, chr.height);
					}

					if (x1 === 'center') {
						x1 = (this.__width / 2) - (width / 2);
					}

					if (y1 === 'center') {
						y1 = (this.__height / 2) - (height / 2);
					}

				}

				var margin = 0;

				for (t = 0, l = text.length; t < l; t++) {

					var chr = font.get(text[t]);

					if (lychee.debug === true) {

						this.drawBox(
							x1 + margin,
							y1,
							x1 + margin + chr.real,
							y1 + chr.height,
							'#ff0',
							false,
							1
						);

					}

					this.__ctx.drawImage(
						chr.sprite || sprite,
						chr.x,
						chr.y,
						chr.width,
						chr.height,
						x1 + margin - settings.spacing,
						y1 + settings.baseline,
						chr.width,
						chr.height
					);

					margin += chr.real + settings.kerning;

				}

			// text based rendering
			} else if (Object.prototype.toString.call(font) === '[object Object]'){

				font.color = typeof font.color === 'string' ? font.color : '#000';
				font.font = typeof font.font === 'string' ? font.font : 'Arial';
				font.size = typeof font.size === 'number' ? font.size : 12;

				if (x1 === 'center' || y1 === 'center') {

					var width = 0;
					for (t = 0, l = text.length; t < l; t++) {
						var m = this.__ctx.measureText(text[t]);
						width += m.charWidth;
					}

					if (x1 === 'center') {
						x1 = (this.__width / 2) - (width / 2);
					}

					if (y1 === 'center') {
						y1 = (this.__height / 2) - (data.size / 2);
					}

				}

				this.__ctx.font = font.size + 'px "' + font.font + '"';
				this.__ctx.fillStyle = font.color;
				this.__ctx.fillText(text, x1, y1);

			}

		}

	};

	return Class;

});

<|endoftext|>


<commit_before>/**
 * Created by rca733 on 1/16/16.
 */
var gzippo = require('gzippo');
var express = require('express');
var app = express();

app.use(express.logger('dev'));
app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.listen(process.env.PORT || 5000);
<commit_msg>one more vraition<commit_after>/**
 * Created by rca733 on 1/16/16.
 */
var gzippo = require('gzippo');
var express = require('express');
var app = express();
var morgan = require('morgan');
var logger = morgan('combined');
var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'})
app.use(morgan('combined', {stream: accessLogStream}));
app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.listen(process.env.PORT || 5000);
<|endoftext|>


<commit_before>/*
 * git-changelog
 * https://github.com/rafinskipg/git-changelog
 */

var child = require('child_process');
var defaults = require('./defaults');
var _ = require('lodash');
var fs = require('fs');
var util = require('util');
var q = require('q');

var OPTS = {};
var PROVIDER, GIT_LOG_CMD, GIT_NOTAG_LOG_CMD,
	//ALLOWED_COMMITS = '^fix|^feat|^docs|BREAKING',
	//git-describe - Show the most recent tag that is reachable from a commit
	GIT_TAG_CMD  = 'git describe --tags --abbrev=0',
	HEADER_TPL = '%s\n# %s (%s)\n\n',
	LINK_ISSUE,
	LINK_COMMIT,
  GIT_REPO_URL_CMD = 'git config --get remote.origin.url',
	EMPTY_COMPONENT = '$$';

// I have to clean that mess

function initOptions(params){
  OPTS = _.defaults(params, defaults);
  OPTS.msg = 'name: '+ OPTS.app_name +';';
  OPTS.msg += 'file: '+ OPTS.file +';';
  OPTS.msg += 'grep_commits: '+ OPTS.grep_commits +';';
  OPTS.msg += 'debug: '+ OPTS.debug +';';
  OPTS.msg += 'version: '+ OPTS.version +';';
}

var init = function(params){
  var deferred = q.defer();

  initOptions(params);

  getRepoUrl().then(function(url){
    OPTS.repo_url = url;
    OPTS.msg += 'remote: '+ OPTS.repo_url+';';

    //G \ B \ ---
    PROVIDER = OPTS.repo_url.indexOf('github.com') !== -1 ? 'G' :'B';

    //Log commits
    GIT_LOG_CMD = 'git log ' + OPTS.branch_name + ' --grep="%s" -E --format=%s %s..HEAD';
    GIT_NOTAG_LOG_CMD = 'git log ' + OPTS.branch_name + ' --grep="%s" -E --format=%s';

    //This is just in case they differ their urls at some point in the future. Also brings the posibility of adding more providers
    LINK_ISSUE = ({
                    G: '[#%s]('+OPTS.repo_url+'/issues/%s)',
                    B : '[#%s]('+OPTS.repo_url+'/issues/%s)'})
                    [PROVIDER];

    LINK_COMMIT = ({
                    G: '[%s]('+OPTS.repo_url+'/commit/%s)',
                    B: '[%s]('+OPTS.repo_url+'/commits/%s)'})
                    [PROVIDER];

    deferred.resolve(OPTS);
  })
  .catch(function(){
    OPTS.msg += 'not remote;';
    deferred.reject("Sorry, you doesn't have configured any origin remote or passed a `repo_url` config value");
  });

  return deferred.promise;
};

var parseRawCommit = function(raw) {
    if (!raw) { return null; }

    var lines = raw.split('\n');
    var msg = {}, match;

    msg.closes = [];
    msg.breaks = [];

    lines.forEach(function(line) {
        match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
        if (match) { msg.closes.push(parseInt(match[1], 10)); }
    });

    msg.hash = lines.shift();
    msg.subject = lines.shift();

    match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
    if (match) {
        msg.breaking = match[1];
    }

    msg.body = lines.join('\n');
    match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);

    if(!match){
        match = msg.subject.match(/^(.*)\:\s(.*)$/);
        if(!match){
            warn('Incorrect message: %s %s', msg.hash, msg.subject);
            return null;
        }
        msg.type = match[1];
        msg.subject = match[2];

        return msg;
    }

    msg.type = match[1];
    msg.component = match[2];
    msg.subject = match[3];
    return msg;
};

var linkToIssue = function(issue) {
    return util.format(LINK_ISSUE, issue, issue);
};

var linkToCommit = function(hash) {
    return util.format(LINK_COMMIT, hash.substr(0, 8), hash);
};

var currentDate = function() {
    var now = new Date();
    var pad = function(i) {
        return ('0' + i).substr(-2);
    };

    return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate()));
};

var printSection = function(stream, title, section, printCommitLinks) {
    printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
    var components = Object.getOwnPropertyNames(section).sort();

    if (!components.length) {return; }

    stream.write(util.format('\n## %s\n\n', title));

    components.forEach(function(name) {
        var prefix = '-';
        var nested = section[name].length > 1;

        if (name !== EMPTY_COMPONENT) {
            if (nested) {
                stream.write(util.format('- **%s:**\n', name));
                prefix = '  -';
            } else {
                prefix = util.format('- **%s:**', name);
            }
        }

        section[name].forEach(function(commit) {
            if (printCommitLinks) {
                stream.write(util.format('%s %s\n  (%s', prefix, commit.subject, linkToCommit(commit.hash)));

                if (commit.closes.length) {
                    stream.write(',\n   ' + commit.closes.map(linkToIssue).join(', '));
                }
                stream.write(')\n');
            } else {
                stream.write(util.format('%s %s\n', prefix, commit.subject));
            }
        });
    });

    stream.write('\n');
};

var printSalute = function(stream){
    stream.write('\n\n---\n');
    stream.write('*Generated with [git-changelog](https://github.com/rafinskipg/git-changelog). If you have any problem or suggestion, create an issue.* :) **Thanks** ');
}

var readGitLog = function( git_log_command, from) {
    var deferred = q.defer();

    git_log_command  =  git_log_command === GIT_LOG_CMD ? util.format(git_log_command, OPTS.grep_commits, '%H%n%s%n%b%n==END==', from) : util.format(git_log_command, OPTS.grep_commits, '%H%n%s%n%b%n==END==');

    log('Executing : ', git_log_command);

    child.exec(git_log_command , {timeout: 1000}, function(code, stdout, stderr) {

        var commits = [];

        stdout.split('\n==END==\n').forEach(function(rawCommit) {

            var commit = parseRawCommit(rawCommit);
            if (commit) {commits.push(commit);}
        });

        deferred.resolve(commits);
    });

    return deferred.promise;
};

var writeChangelog = function(stream, commits) {
    var sections = {
      fix: {},
      feat: {},
      breaks: {},
      style: {},
      refactor: {},
      test: {},
      chore: {},
      docs: {}
    };

    sections.breaks[EMPTY_COMPONENT] = [];

    organizeCommitsInSections(commits, sections)

    stream.write(util.format(HEADER_TPL, OPTS.version, OPTS.app_name, OPTS.version, currentDate()));
    printSection(stream, 'Bug Fixes', sections.fix);
    printSection(stream, 'Features', sections.feat);
    printSection(stream, 'Refactor', sections.refactor, false);
    printSection(stream, 'Style', sections.style, false);
    printSection(stream, 'Test', sections.test, false);
    printSection(stream, 'Chore', sections.chore, false);
    printSection(stream, 'Documentation', sections.docs, false);
    if(sections.breaks[EMPTY_COMPONENT].length > 0 ) {
        printSection(stream, 'Breaking Changes', sections.breaks, false);
    }

    printSalute(stream);
};

var organizeCommitsInSections = function(commits, sections){
    commits.forEach(function(commit) {
        var section = sections[commit.type];
        var component = commit.component || EMPTY_COMPONENT;

        if (section) {
            section[component] = section[component] || [];
            section[component].push(commit);
        }

        if (commit.breaking) {
            sections.breaks[component] = sections.breaks[component] || [];
            sections.breaks[component].push({
                subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
                hash: commit.hash,
                closes: []
            });
        }
    });
    return sections;
}

var getPreviousTag = function() {
    var deferred = q.defer();
    if(OPTS.tag){
      deferred.resolve(OPTS.tag);
    }else if(OPTS.tag === false){
      deferred.resolve(false);
    }else{
      //IF we dont find a previous tag, we get all the commits from the beggining - The bigbang of the code
      child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
        if (code ){ deferred.resolve();
        }else{
          deferred.resolve(stdout.replace('\n', ''));
        }
      });
    }

    return deferred.promise;
};

var getRepoUrl = function() {
  var deferred = q.defer();

  if(OPTS.repo_url){
    deferred.resolve(OPTS.repo_url);
  }else{
    //IF we dont find a previous tag, we get all the commits from the beggining - The bigbang of the code
    child.exec(GIT_REPO_URL_CMD, function(code, stdout, stderr) {
      if (code){
        deferred.reject();
      } else {
        stdout = stdout.replace('\n', '').replace('.git', '');
        deferred.resolve(stdout);
      }
    });
  }

  return deferred.promise;
};

var generate = function(params) {
  var deferred = q.defer();
  init(params)
  .then(function(){
    return getPreviousTag()
  })
  .then(function(tag) {
      var fn ;

      if(typeof(tag) !== 'undefined' && tag !== false){
          log('Reading git log since', tag);
          OPTS.msg += 'since tag: '+ tag +';';
          fn = function(){ return readGitLog(GIT_LOG_CMD, tag);};
      }else{
          log('Reading git log since the beggining');
          OPTS.msg += 'since beggining;';
          fn = function(){ return readGitLog(GIT_NOTAG_LOG_CMD);};
      }

      fn().then(function(commits) {
        OPTS.msg += 'parsed commits:'+ commits.length +';';
        log('Parsed', commits.length, 'commits');
        log('Generating changelog to', OPTS.file || 'stdout', '(', OPTS.version, ')');
        writeChangelog(OPTS.file ? fs.createWriteStream(OPTS.file) : process.stdout, commits);
        deferred.resolve(OPTS);
      })
      .catch(function(err){
        console.log('error', err);
      })

  })
  .catch(function(err){
    console.log('Error generating changelog ', err);
    deferred.reject(err);
  })

  return deferred.promise;
};

function log(){
  if(OPTS.debug){
    console.log.apply(console, arguments);
  }
}

var warn = function() {
  if(OPTS.debug){
    console.log('WARNING:', util.format.apply(null, arguments));
  }
};

// publish for testing
exports.parseRawCommit = parseRawCommit;
exports.organizeCommitsInSections = organizeCommitsInSections;
exports.generate = generate;
exports.getRepoUrl = getRepoUrl;

<commit_msg>refactor: modified the task using a factory pattern to improve testability<commit_after>/*
 * git-changelog
 * https://github.com/rafinskipg/git-changelog
 */

var fs = require('fs');
var child = require('child_process');
var format = require('util').format;

var _ = require('lodash');
var q = require('q');

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

//ALLOWED_COMMITS = '^fix|^feat|^docs|BREAKING',
//git-describe - Show the most recent tag that is reachable from a commit
var GIT_TAG_CMD  = 'git describe --tags --abbrev=0';
var HEADER_TPL = '%s\n# %s (%s)\n\n';
var GIT_REPO_URL_CMD = 'git config --get remote.origin.url';
var EMPTY_COMPONENT = '$$';
var GIT_LOG_CMD;
var GIT_NOTAG_LOG_CMD;
var LINK_ISSUE;
var LINK_COMMIT;

// I have to clean that mess

var Changelog = function Changelog() {
  this.options = {};
  this.options.msg = '';
};

Changelog.prototype.message = function message() {
  Array.prototype.slice.call(arguments).forEach(function(value, index) {
    this.options.msg += (index ? ': ' : '') + value;
  }, this);

  this.options.msg += ';';
};

Changelog.prototype.initOptions = function initOptions(params) {
  this.options = _.defaults(params, defaults);

  this.message('name', this.options.app_name);
  this.message('file', this.options.file);
  this.message('grep_commits', this.options.grep_commits);
  this.message('debug', this.options.debug);
  this.message('version', this.options.version);
};

Changelog.prototype.init = function init(params) {
  var self = this;
  var deferred = q.defer();

  this.initOptions(params);

  this.getRepoUrl().then(function(url) {
    var provider;

    self.options.repo_url = url;
    self.message('remote', self.options.repo_url);

    //G \ B \ ---
    provider = self.options.repo_url.indexOf('github.com') !== -1 ? 'G' :'B';

    //Log commits
    GIT_LOG_CMD = 'git log ' + self.options.branch_name + ' --grep="%s" -E --format=%s %s..HEAD';
    GIT_NOTAG_LOG_CMD = 'git log ' + self.options.branch_name + ' --grep="%s" -E --format=%s';

    //This is just in case they differ their urls at some point in the future. Also brings the posibility of adding more providers
    LINK_ISSUE = ({
                    G: '[#%s]('+self.options.repo_url+'/issues/%s)',
                    B : '[#%s]('+self.options.repo_url+'/issues/%s)'})
                    [provider];

    LINK_COMMIT = ({
                    G: '[%s]('+self.options.repo_url+'/commit/%s)',
                    B: '[%s]('+self.options.repo_url+'/commits/%s)'})
                    [provider];

    deferred.resolve(self.options);
  })
  .catch(function() {
    self.message('not remote');
    deferred.reject("Sorry, you doesn't have configured any origin remote or passed a `repo_url` config value");
  });

  return deferred.promise;
};

Changelog.prototype.parseRawCommit = function parseRawCommit(raw) {
  if (!raw) {
    return null;
  }

  var lines = raw.split('\n');
  var msg = {}, match;

  msg.closes = [];
  msg.breaks = [];

  lines.forEach(function(line) {
    match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
    if (match) {
      msg.closes.push(parseInt(match[1], 10));
    }
  });

  msg.hash = lines.shift();
  msg.subject = lines.shift();

  match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
  if (match) {
    msg.breaking = match[1];
  }

  msg.body = lines.join('\n');
  match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);

  if (!match) {
    match = msg.subject.match(/^(.*)\:\s(.*)$/);
    if (!match) {
      this.warn('Incorrect message: %s %s', msg.hash, msg.subject);
      return null;
    }
    msg.type = match[1];
    msg.subject = match[2];

    return msg;
  }

  msg.type = match[1];
  msg.component = match[2];
  msg.subject = match[3];

  return msg;
};

Changelog.prototype.linkToIssue = function linkToIssue(issue) {
  return format(LINK_ISSUE, issue, issue);
};

Changelog.prototype.linkToCommit = function linkToCommit(hash) {
  return format(LINK_COMMIT, hash.substr(0, 8), hash);
};

Changelog.prototype.currentDate = function currentDate() {
  var now = new Date();
  var pad = function(i) {
    return ('0' + i).substr(-2);
  };

  return format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate()));
};

Changelog.prototype.printSection = function printSection(stream, title, section, printCommitLinks) {
  printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
  var components = Object.keys(section).sort();

  if (!components.length) {
    return;
  }

  stream.write(format('\n## %s\n\n', title));

  components.forEach(function(name) {
    var prefix = '-';
    var nested = section[name].length > 1;

    if (name !== EMPTY_COMPONENT) {
      if (nested) {
        stream.write(format('- **%s:**\n', name));
        prefix = '  -';
      } else {
        prefix = format('- **%s:**', name);
      }
    }

    section[name].forEach(function(commit) {
      if (printCommitLinks) {
        stream.write(format('%s %s\n  (%s', prefix, commit.subject, this.linkToCommit(commit.hash)));

        if (commit.closes.length) {
          stream.write(',\n   ' + commit.closes.map(this.linkToIssue).join(', '));
        }
        stream.write(')\n');
      } else {
        stream.write(format('%s %s\n', prefix, commit.subject));
      }
    }, this);
  }, this);

  stream.write('\n');
};

Changelog.prototype.printSalute = function printSalute(stream) {
  stream.write('\n\n---\n');
  stream.write('*Generated with [git-changelog](https://github.com/rafinskipg/git-changelog). If you have any problem or suggestion, create an issue.* :) **Thanks** ');
};

Changelog.prototype.readGitLog = function prototype( git_log_command, from) {
  var self = this;
  var deferred = q.defer();

  git_log_command  =  git_log_command === GIT_LOG_CMD ? format(git_log_command, this.options.grep_commits, '%H%n%s%n%b%n==END==', from) : format(git_log_command, this.options.grep_commits, '%H%n%s%n%b%n==END==');

  this.log('Executing : ', git_log_command);

  child.exec(git_log_command , {timeout: 1000}, function(code, stdout, stderr) {
    var commits = [];

    stdout.split('\n==END==\n').forEach(function(rawCommit) {
      var commit = self.parseRawCommit(rawCommit);
      if (commit) {
        commits.push(commit);
      }
    });

    deferred.resolve(commits);
  });

  return deferred.promise;
};

Changelog.prototype.writeChangelog = function writeChangelog(stream, commits) {
  var sections = {
    fix: {},
    feat: {},
    breaks: {},
    style: {},
    refactor: {},
    test: {},
    chore: {},
    docs: {}
  };

  sections.breaks[EMPTY_COMPONENT] = [];

  this.organizeCommitsInSections(commits, sections);

  stream.write(format(HEADER_TPL, this.options.version, this.options.app_name, this.options.version, this.currentDate()));
  this.printSection(stream, 'Bug Fixes', sections.fix);
  this.printSection(stream, 'Features', sections.feat);
  this.printSection(stream, 'Refactor', sections.refactor, false);
  this.printSection(stream, 'Style', sections.style, false);
  this.printSection(stream, 'Test', sections.test, false);
  this.printSection(stream, 'Chore', sections.chore, false);
  this.printSection(stream, 'Documentation', sections.docs, false);
  if (sections.breaks[EMPTY_COMPONENT].length > 0 ) {
    this.printSection(stream, 'Breaking Changes', sections.breaks, false);
  }

  this.printSalute(stream);
};

Changelog.prototype.organizeCommitsInSections = function organizeCommitsInSections(commits, sections) {
  commits.forEach(function(commit) {
    var section = sections[commit.type];
    var component = commit.component || EMPTY_COMPONENT;

    if (section) {
      section[component] = section[component] || [];
      section[component].push(commit);
    }

    if (commit.breaking) {
      sections.breaks[component] = sections.breaks[component] || [];
      sections.breaks[component].push({
        subject: format("due to %s,\n %s", this.linkToCommit(commit.hash), commit.breaking),
        hash: commit.hash,
        closes: []
      });
    }
  }, this);

  return sections;
};

Changelog.prototype.getPreviousTag = function getPreviousTag() {
  var deferred = q.defer();

  if (this.options.tag) {
    deferred.resolve(this.options.tag);
  } else if (this.options.tag === false) {
    deferred.resolve(false);
  } else {
    //IF we dont find a previous tag, we get all the commits from the beggining - The bigbang of the code
    child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
      if (code ) {
        deferred.resolve();
      } else {
        deferred.resolve(stdout.replace('\n', ''));
      }
    });
  }

  return deferred.promise;
};

Changelog.prototype.getRepoUrl = function getRepoUrl() {
  var deferred = q.defer();

  if (this.options.repo_url) {
    deferred.resolve(this.options.repo_url);
  } else {
    //IF we dont find a previous tag, we get all the commits from the beggining - The bigbang of the code
    child.exec(GIT_REPO_URL_CMD, function(code, stdout, stderr) {
      if (code) {
        deferred.reject();
      } else {
        stdout = stdout.replace('\n', '').replace('.git', '');
        deferred.resolve(stdout);
      }
    });
  }

  return deferred.promise;
};

Changelog.prototype.generate = function generate(params) {
  var self = this;
  var deferred = q.defer();

  this.init(params).then(function() {
    return self.getPreviousTag();
  }).then(function(tag) {
    var fn;

    if (typeof(tag) !== 'undefined' && tag !== false) {
      self.log('Reading git log since', tag);
      self.message('since tag', tag);

      fn = function() {
        return self.readGitLog(GIT_LOG_CMD, tag);
      }

    }else{
      self.log('Reading git log since the beggining');
      self.message('since beggining');

      fn = function() {
        return self.readGitLog(GIT_NOTAG_LOG_CMD);
      }
    }

    fn().then(function(commits) {
      self.message('parsed commits', commits.length);
      self.log('Parsed', commits.length, 'commits');
      self.log('Generating changelog to', self.options.file || 'stdout', '(', self.options.version, ')');

      self.writeChangelog(self.options.file ? fs.createWriteStream(self.options.file) : process.stdout, commits);

      deferred.resolve(self.options);
    }).catch(function(err) {
      console.log('error', err);
    });
  }).catch(function(err) {
    console.log('Error generating changelog ', err);
    deferred.reject(err);
  });

  return deferred.promise;
};

Changelog.prototype.log = function log() {
  if (this.options.debug) {
    console.log.apply(console, arguments);
  }
};

Changelog.prototype.warn = function warn() {
  this.log('WARNING:', format.apply(null, arguments));
};

module.exports = new Changelog();
<|endoftext|>


<commit_before>/*
Input.js is MIT-licensed software
Copyright (c) 2011 Jon Buckley
*/

(function() {
  // Holds all of the physical device to USB enumeration mappings
  var keymapBlob = {
    '45e' : { /* Microsoft */
      '28e' : { /* Xbox 360 controller */
        'Mac' : {
          'axes' : {
            'Left_Stick_X': 0,
            'Left_Stick_Y': 1,
            'Right_Stick_X': 2,
            'Right_Stick_Y': 3,
            'Left_Trigger_2': [4, -1, 1],
            'Right_Trigger_2': [5, -1, 1]
          },
          'buttons' : {
            'A_Button': 0,
            'B_Button': 1,
            'X_Button': 2,
            'Y_Button': 3,
            'Left_Trigger_1': 4,
            'Right_Trigger_1': 5,
            'Left_Stick_Button': 6,
            'Right_Stick_Button': 7,
            'Start_Button': 8,
            'Back_Button': 9,
            'Home_Button': 10,
            'Pad_Up': 11,
            'Pad_Down': 12,
            'Pad_Left': 13,
            'Pad_Right': 14
          }
        },
        "Win": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_X": 3,
            "Right_Stick_Y": 4,
            "Pad_Left": [5, -1, 0],
            "Pad_Right": [5, 0, 1],
            "Pad_Up": [6, -1, 0],
            "Pad_Down": [6, 0, 1],
            "Left_Trigger_2": [2, 0, 1],
            "Right_Trigger_2": [2, -1, 0]
          },
          "buttons": {
            "A_Button": 0,
            "B_Button": 1,
            "X_Button": 2,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Back_Button": 6,
            "Start_Button": 7,
            "Left_Stick_Button": 8,
            "Right_Stick_Button": 9
          }
        }
      }
    },
    "54c": { /* Sony */
      "268": { /* PS3 Controller */
        "Mac": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_X": 2,
            "Right_Stick_Y": 3
          },
          "buttons": {
            "Back_Button": 0,
            "Left_Stick_Button": 1,
            "Right_Stick_Button": 2,
            "Start_Button": 3,
            "Pad_Up": 4,
            "Pad_Down": 6,
            "Pad_Right": 5,
            "Pad_Left": 7,
            "Left_Trigger_2": 8,
            "Right_Trigger_2": 9,
            "Left_Trigger_1": 10,
            "Right_Trigger_1": 11,
            "Y_Button": 12,
            "B_Button": 13,
            "A_Button": 14,
            "X_Button": 15,
            "Home_Button": 16
          }
        }
      }
    },
    "46d": { /* Logitech */
      "c242": { /* Chillstream */
        "Win": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_Y": 4,
            "Right_Stick_X": 3,
            "Left_Trigger_2": [2, 0, 1],
            "Right_Trigger_2": [2, -1, 0],
            "Pad_Left": [5, -1, 0],
            "Pad_Right": [5, 0, 1],
            "Pad_Up": [6, -1, 0],
            "Pad_Down": [6, 0, 1]
          },
          "buttons": {
            "A_Button": 0,
            "X_Button": 2,
            "B_Button": 1,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Back_Button": 6,
            "Start_Button": 7,
            "Left_Stick_Button": 8,
            "Right_Stick_Button": 9
          }
        }
      },
      "c216": { /* Dual Action */
        "Mac": {
          "axes": {
            "Left_Stick_X": 1,
            "Left_Stick_Y": 2,
            "Right_Stick_X": 3,
            "Right_Stick_Y": 4,
            "Pad_Left": [1, 0, -1],
            "Pad_Right": [1, 0, 1],
            "Pad_Up": [2, 0, -1],
            "Pad_Down": [2, 0, 1]
          },
          "buttons": {
            "X_Button": 0,
            "A_Button": 1,
            "B_Button": 2,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Left_Trigger_2": 6,
            "Right_Trigger_2": 7,
            "Back_Button": 8,
            "Start_Button": 9,
            "Left_Stick_Button": 10,
            "Right_Stick_Button": 11
          }
        }
      }
    },
    "40b": {
      "6533": { /* USB 2A4K GamePad */
        "Mac": {
          "axes": {
            "Pad_Left": [0, 0, -1],
            "Pad_Right": [0, 0, 1],
            "Pad_Up": [1, 0, -1],
            "Pad_Down": [1, 0, 1]
          },
          "buttons": {
            "A_Button": 0,
            "B_Button": 1,
            "X_Button": 2,
            "Y_Button": 3
          }
        }
      }
    },
    "Firefox": {
      "Fake Gamepad": {
        "Mac": {
          "axes": {

          },
          "buttons": {
            'A_Button' : 0,
            'B_Button' : 1,
            'X_Button' : 2,
            'Y_Button' : 3,
            'Pad_Up' : 4,
            'Pad_Down': 5,
            'Pad_Left': 6,
            'Pad_Right': 7
          }
        }
      }
    }
  };

  // Our ideal gamepad that we present to the developer
  var ImaginaryGamepad = {
    'axes' : [
      'Left_Stick_X',
      'Left_Stick_Y',
      'Right_Stick_X',
      'Right_Stick_Y'
    ],
    'buttons' : [
      'A_Button',
      'B_Button',
      'X_Button',
      'Y_Button',
      'Left_Stick_Button',
      'Right_Stick_Button',
      'Start_Button',
      'Back_Button',
      'Home_Button',
      'Pad_Up',
      'Pad_Down',
      'Pad_Left',
      'Pad_Right',
      'Left_Trigger_1',
      'Right_Trigger_1',
      'Left_Trigger_2',
      'Right_Trigger_2'
    ]
  };

  var osList = ['Win', 'Mac', 'Linux'];
  function detectOS() {
    for (var i in osList) {
      if (navigator.platform.indexOf(osList[i]) !== -1) {
        return osList[i];
      }
    }
    return 'Unknown';
  }

  function map(value, istart, istop, ostart, ostop) {
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
  };

  // Map imaginary device action to physical device action
  function mapAxisToAxis(device, keymap, axes, prop) {
    Object.defineProperty(axes, prop, {
      enumerable: true,
      get: function() { return device.axes[keymap.axes[prop]]; }
    });
  }

  function mapAxisToButton(device, keymap, axes, prop) {
    Object.defineProperty(axes, prop, {
      enumerable: true,
      get: function() { return 0; }
    });
  }

  function mapButtonToButton(device, keymap, buttons, prop) {
    Object.defineProperty(buttons, prop, {
      enumerable: true,
      get: function() { return device.buttons[keymap.buttons[prop]]; }
    });
  }

  function mapButtonToAxis(device, keymap, buttons, prop) {
    var transform = keymap.axes[prop] instanceof Array;

    Object.defineProperty(buttons, prop, {
      enumerable: true,
      get: function() {
        if (transform) {
          return map(device.axes[keymap.axes[prop][0]], keymap.axes[prop][1], keymap.axes[prop][2], 0, 1);
        } else {
          return device.axes[keymap.axes[prop]];
        }
      }
    });
  }

  function mapZero(type, prop) {
    Object.defineProperty(type, prop, {
      enumerable: true,
      get: function() { return 0; }
    });
  }

  var Input = window.Input = {};
  var Device = Input.Device = function(domGamepad) {
    if (!domGamepad) {
      throw "You didn't pass a valid gamepad to the constructor";
    }

    var device = domGamepad,
        usbVendor = domGamepad.id.split('-')[0],
        usbDevice = domGamepad.id.split('-')[1],
        os = detectOS(),
        keymap = keymapBlob,
        axes = this.axes = {},
        buttons = this.buttons = {};

    if (keymap && keymap[usbVendor] && keymap[usbVendor][usbDevice] && keymap[usbVendor][usbDevice][os]) {
      keymap = keymap[usbVendor][usbDevice][os];
    } else {
      throw "A physical device layout for " + usbVendor + "-" + usbDevice + "-" + os + " isn't available";
    }

    // Wire the axes and buttons up
    for (var a in ImaginaryGamepad.axes) {
      if (keymap.axes[ImaginaryGamepad.axes[a]] !== undefined) {
        mapAxisToAxis(device, keymap, axes, ImaginaryGamepad.axes[a]);
      } else if (keymap.buttons[ImaginaryGamepad.axes[a]] !== undefined) {
        mapAxisToButton(device, keymap, axes, ImaginaryGamepad.axes[a]);
      } else {
        mapZero(axes, ImaginaryGamepad.axes[a]);
      }
    }

    for (var b in ImaginaryGamepad.buttons) {
      if (keymap.buttons[ImaginaryGamepad.buttons[b]] !== undefined) {
        mapButtonToButton(device, keymap, buttons, ImaginaryGamepad.buttons[b]);
      } else if (keymap.axes[ImaginaryGamepad.buttons[b]] !== undefined) {
        mapButtonToAxis(device, keymap, buttons, ImaginaryGamepad.buttons[b]);
      } else {
        mapZero(buttons, ImaginaryGamepad.buttons[b]);
      }
    }

    // Add some useful properties from the DOMGamepad object
    Object.defineProperty(this, "connected", {
      enumerable: true,
      get: function() { return device.connected; }
    });

    Object.defineProperty(this, "id", {
      enumerable: true,
      get: function() { return device.id; }
    });

    Object.defineProperty(this, "index", {
      enumerable: true,
      get: function() { return device.index; }
    });
  };
}());
<commit_msg>Fix Xbox 360 Right Trigger 2 values<commit_after>/*
Input.js is MIT-licensed software
Copyright (c) 2011 Jon Buckley
*/

(function() {
  // Holds all of the physical device to USB enumeration mappings
  var keymapBlob = {
    '45e' : { /* Microsoft */
      '28e' : { /* Xbox 360 controller */
        'Mac' : {
          'axes' : {
            'Left_Stick_X': 0,
            'Left_Stick_Y': 1,
            'Right_Stick_X': 2,
            'Right_Stick_Y': 3,
            'Left_Trigger_2': [4, -1, 1],
            'Right_Trigger_2': [5, -1, 1]
          },
          'buttons' : {
            'A_Button': 0,
            'B_Button': 1,
            'X_Button': 2,
            'Y_Button': 3,
            'Left_Trigger_1': 4,
            'Right_Trigger_1': 5,
            'Left_Stick_Button': 6,
            'Right_Stick_Button': 7,
            'Start_Button': 8,
            'Back_Button': 9,
            'Home_Button': 10,
            'Pad_Up': 11,
            'Pad_Down': 12,
            'Pad_Left': 13,
            'Pad_Right': 14
          }
        },
        "Win": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_X": 3,
            "Right_Stick_Y": 4,
            "Pad_Left": [5, -1, 0],
            "Pad_Right": [5, 0, 1],
            "Pad_Up": [6, -1, 0],
            "Pad_Down": [6, 0, 1],
            "Left_Trigger_2": [2, 0, 1],
            "Right_Trigger_2": [2, 0, -1]
          },
          "buttons": {
            "A_Button": 0,
            "B_Button": 1,
            "X_Button": 2,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Back_Button": 6,
            "Start_Button": 7,
            "Left_Stick_Button": 8,
            "Right_Stick_Button": 9
          }
        }
      }
    },
    "54c": { /* Sony */
      "268": { /* PS3 Controller */
        "Mac": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_X": 2,
            "Right_Stick_Y": 3
          },
          "buttons": {
            "Back_Button": 0,
            "Left_Stick_Button": 1,
            "Right_Stick_Button": 2,
            "Start_Button": 3,
            "Pad_Up": 4,
            "Pad_Down": 6,
            "Pad_Right": 5,
            "Pad_Left": 7,
            "Left_Trigger_2": 8,
            "Right_Trigger_2": 9,
            "Left_Trigger_1": 10,
            "Right_Trigger_1": 11,
            "Y_Button": 12,
            "B_Button": 13,
            "A_Button": 14,
            "X_Button": 15,
            "Home_Button": 16
          }
        }
      }
    },
    "46d": { /* Logitech */
      "c242": { /* Chillstream */
        "Win": {
          "axes": {
            "Left_Stick_X": 0,
            "Left_Stick_Y": 1,
            "Right_Stick_Y": 4,
            "Right_Stick_X": 3,
            "Left_Trigger_2": [2, 0, 1],
            "Right_Trigger_2": [2, -1, 0],
            "Pad_Left": [5, -1, 0],
            "Pad_Right": [5, 0, 1],
            "Pad_Up": [6, -1, 0],
            "Pad_Down": [6, 0, 1]
          },
          "buttons": {
            "A_Button": 0,
            "X_Button": 2,
            "B_Button": 1,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Back_Button": 6,
            "Start_Button": 7,
            "Left_Stick_Button": 8,
            "Right_Stick_Button": 9
          }
        }
      },
      "c216": { /* Dual Action */
        "Mac": {
          "axes": {
            "Left_Stick_X": 1,
            "Left_Stick_Y": 2,
            "Right_Stick_X": 3,
            "Right_Stick_Y": 4,
            "Pad_Left": [1, 0, -1],
            "Pad_Right": [1, 0, 1],
            "Pad_Up": [2, 0, -1],
            "Pad_Down": [2, 0, 1]
          },
          "buttons": {
            "X_Button": 0,
            "A_Button": 1,
            "B_Button": 2,
            "Y_Button": 3,
            "Left_Trigger_1": 4,
            "Right_Trigger_1": 5,
            "Left_Trigger_2": 6,
            "Right_Trigger_2": 7,
            "Back_Button": 8,
            "Start_Button": 9,
            "Left_Stick_Button": 10,
            "Right_Stick_Button": 11
          }
        }
      }
    },
    "40b": {
      "6533": { /* USB 2A4K GamePad */
        "Mac": {
          "axes": {
            "Pad_Left": [0, 0, -1],
            "Pad_Right": [0, 0, 1],
            "Pad_Up": [1, 0, -1],
            "Pad_Down": [1, 0, 1]
          },
          "buttons": {
            "A_Button": 0,
            "B_Button": 1,
            "X_Button": 2,
            "Y_Button": 3
          }
        }
      }
    },
    "Firefox": {
      "Fake Gamepad": {
        "Mac": {
          "axes": {

          },
          "buttons": {
            'A_Button' : 0,
            'B_Button' : 1,
            'X_Button' : 2,
            'Y_Button' : 3,
            'Pad_Up' : 4,
            'Pad_Down': 5,
            'Pad_Left': 6,
            'Pad_Right': 7
          }
        }
      }
    }
  };

  // Our ideal gamepad that we present to the developer
  var ImaginaryGamepad = {
    'axes' : [
      'Left_Stick_X',
      'Left_Stick_Y',
      'Right_Stick_X',
      'Right_Stick_Y'
    ],
    'buttons' : [
      'A_Button',
      'B_Button',
      'X_Button',
      'Y_Button',
      'Left_Stick_Button',
      'Right_Stick_Button',
      'Start_Button',
      'Back_Button',
      'Home_Button',
      'Pad_Up',
      'Pad_Down',
      'Pad_Left',
      'Pad_Right',
      'Left_Trigger_1',
      'Right_Trigger_1',
      'Left_Trigger_2',
      'Right_Trigger_2'
    ]
  };

  var osList = ['Win', 'Mac', 'Linux'];
  function detectOS() {
    for (var i in osList) {
      if (navigator.platform.indexOf(osList[i]) !== -1) {
        return osList[i];
      }
    }
    return 'Unknown';
  }

  function map(value, istart, istop, ostart, ostop) {
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
  };

  // Map imaginary device action to physical device action
  function mapAxisToAxis(device, keymap, axes, prop) {
    Object.defineProperty(axes, prop, {
      enumerable: true,
      get: function() { return device.axes[keymap.axes[prop]]; }
    });
  }

  function mapAxisToButton(device, keymap, axes, prop) {
    Object.defineProperty(axes, prop, {
      enumerable: true,
      get: function() { return 0; }
    });
  }

  function mapButtonToButton(device, keymap, buttons, prop) {
    Object.defineProperty(buttons, prop, {
      enumerable: true,
      get: function() { return device.buttons[keymap.buttons[prop]]; }
    });
  }

  function mapButtonToAxis(device, keymap, buttons, prop) {
    var transform = keymap.axes[prop] instanceof Array;

    Object.defineProperty(buttons, prop, {
      enumerable: true,
      get: function() {
        if (transform) {
          return map(device.axes[keymap.axes[prop][0]], keymap.axes[prop][1], keymap.axes[prop][2], 0, 1);
        } else {
          return device.axes[keymap.axes[prop]];
        }
      }
    });
  }

  function mapZero(type, prop) {
    Object.defineProperty(type, prop, {
      enumerable: true,
      get: function() { return 0; }
    });
  }

  var Input = window.Input = {};
  var Device = Input.Device = function(domGamepad) {
    if (!domGamepad) {
      throw "You didn't pass a valid gamepad to the constructor";
    }

    var device = domGamepad,
        usbVendor = domGamepad.id.split('-')[0],
        usbDevice = domGamepad.id.split('-')[1],
        os = detectOS(),
        keymap = keymapBlob,
        axes = this.axes = {},
        buttons = this.buttons = {};

    if (keymap && keymap[usbVendor] && keymap[usbVendor][usbDevice] && keymap[usbVendor][usbDevice][os]) {
      keymap = keymap[usbVendor][usbDevice][os];
    } else {
      throw "A physical device layout for " + usbVendor + "-" + usbDevice + "-" + os + " isn't available";
    }

    // Wire the axes and buttons up
    for (var a in ImaginaryGamepad.axes) {
      if (keymap.axes[ImaginaryGamepad.axes[a]] !== undefined) {
        mapAxisToAxis(device, keymap, axes, ImaginaryGamepad.axes[a]);
      } else if (keymap.buttons[ImaginaryGamepad.axes[a]] !== undefined) {
        mapAxisToButton(device, keymap, axes, ImaginaryGamepad.axes[a]);
      } else {
        mapZero(axes, ImaginaryGamepad.axes[a]);
      }
    }

    for (var b in ImaginaryGamepad.buttons) {
      if (keymap.buttons[ImaginaryGamepad.buttons[b]] !== undefined) {
        mapButtonToButton(device, keymap, buttons, ImaginaryGamepad.buttons[b]);
      } else if (keymap.axes[ImaginaryGamepad.buttons[b]] !== undefined) {
        mapButtonToAxis(device, keymap, buttons, ImaginaryGamepad.buttons[b]);
      } else {
        mapZero(buttons, ImaginaryGamepad.buttons[b]);
      }
    }

    // Add some useful properties from the DOMGamepad object
    Object.defineProperty(this, "connected", {
      enumerable: true,
      get: function() { return device.connected; }
    });

    Object.defineProperty(this, "id", {
      enumerable: true,
      get: function() { return device.id; }
    });

    Object.defineProperty(this, "index", {
      enumerable: true,
      get: function() { return device.index; }
    });
  };
}());
<|endoftext|>


<commit_before><commit_msg>Update namespace<commit_after><|endoftext|>


<commit_before>var mongoose = require('mongoose'),
    _ = require('lodash'),
    Schema = mongoose.Schema,
    ObjectId = Schema.Types.ObjectId,
    models = {};

module.exports = function (schema, options) {
    options = options || {};
    var primaryKeyName = options.primaryKeyName || '_id';

    var getHistoricalModel = function (model) {
        var connection = options.connection || model.constructor.collection.conn,
            name = options.name || model.constructor.modelName + 's_historical';

        if (!model.constructor.schema.paths[primaryKeyName]) {
            throw new Error('Historical error: Missing primary key `' + primaryKeyName + '` in schema `' + name + '`.');
        }

        var primaryKeyType = (options.primaryKeyType || /* deprecated */ options.idType) || (model.constructor.schema.paths[primaryKeyName].options.type || ObjectId);

        models[model.constructor.modelName] = models[model.constructor.modelName] === undefined ?
            connection.model(name, new Schema({
                document: { type: primaryKeyType, index: true },
                timestamp: {type: Date, default: Date.now, index: true},
                diff: Schema.Types.Mixed
            })) : models[model.constructor.modelName];

        return models[model.constructor.modelName];
    };

    var read = function (o, p) {
        for (var i = 0, a = p.split('.'), l = a.length; i < l; i++) {
            o = o[a[i]];
        }
        return o;
    };

    var write = function (o, p, v) {
        for (var i = 0, a = p.split('.'); i < a.length - 1; i++) {
            var n = a[i];
            if (n in o) {
                o = o[n];
            } else {
                o[n] = {};
                o = o[n];
            }
        }
        o[a[a.length - 1]] = v;
    };

    schema.pre('save', function (next) {
        var me = this,
            HistoricalModel = getHistoricalModel(me),
            modified = _.uniq(me.modifiedPaths()),
            diff = {};

        modified.forEach(function (index) {
            var value = read(me, index);
            if (_.isObject(value) && !_.isArray(value)) {
                return;
            }
            if (value === undefined) {
                write(diff, index, null);
                return;
            }
            write(diff, index, value);
        });

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: diff
        });
        historical.save(next);
    });

    schema.pre('remove', function (next) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: null
        });
        historical.save(next);
    });

    schema.methods.historicalSnapshot = function (callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (me.modifiedPaths().length) {
            return callback(new Error('Historical error: Attempted to snapshot an unsaved/modified document.'));
        }

        var snapshot = me.toObject();
        delete snapshot[primaryKeyName];
        delete snapshot.__v;

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: snapshot
        });
        historical.save(function (e) {
            if (e) {
                return callback(e);
            }
            return callback(null, me);
        });
    };

    schema.methods.historicalClear = function (callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        HistoricalModel.find({document: me[primaryKeyName]}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            me.historicalSnapshot(function (e) {
                if (e) {
                    return callback(e);
                }
                objs.forEach(function (obj) {
                    obj.remove();
                });
                return callback(null, me);
            });
        });
    };

    schema.methods.historicalRestore = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me),
            surrogate = {};

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        HistoricalModel.find({document: me[primaryKeyName], timestamp: {$lte: date}}, null, {sort: {timestamp: 1}}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            if (!objs) {
                return callback(null, null);
            }

            objs.forEach(function (obj) {
                if (!obj.diff) {
                    surrogate = null;
                }
                else {
                    surrogate = _.merge(surrogate, obj.diff);
                }
            });

            if (!surrogate) {
                return callback(null, null);
            }

            me.set(_.merge(me.toObject(), surrogate));
            return callback(null, me);
        });
    };

    schema.methods.historicalTrim = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        me.historicalRestore(date, function (e, obj) {
            if (e) {
                return callback(e);
            }
            if (!obj) {
                return callback(null, me);
            }
            HistoricalModel.remove({document: me[primaryKeyName], timestamp: {$lte: date}}, function (e) {
                if (e) {
                    return callback(e);
                }
                var trimmed = new HistoricalModel({
                    document: me[primaryKeyName],
                    diff: obj.toObject(),
                    timestamp: date
                });
                trimmed.save(function (e) {
                    if (e) {
                        return callback(e);
                    }
                    return callback(null, me);
                });
            });
        });
    };

    schema.methods.historicalDetails = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        HistoricalModel.find({document: me[primaryKeyName], timestamp: {$lte: date}}, null, {sort: {timestamp: 1}}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            return callback(null, objs);
        });
    };

    schema.methods.historical = function () {
        var me = this,
            action = null,
            date = new Date(),
            callback = function () {
            },
            args = Array.prototype.slice.call(arguments, 0, 3);

        if (_.isString(args[0])) {
            action = args[0];
        }

        if (_.isDate(args[1])) {
            date = args[1];
        }

        if (_.isFunction(args[args.length - 1])) {
            callback = args[args.length - 1];
        }

        switch (action) {
            case 'snapshot':
                me.historicalSnapshot(callback);
                break;
            case 'clear':
                me.historicalClear(callback);
                break;
            case 'restore':
                me.historicalRestore(date, callback);
                break;
            case 'trim':
                me.historicalTrim(date, callback);
                break;
            case 'history':
            case 'details':
            default:
                me.historicalDetails(date, callback);
        }
    };
};
<commit_msg>Correct primaryKeyType assignment location<commit_after>var mongoose = require('mongoose'),
    _ = require('lodash'),
    Schema = mongoose.Schema,
    ObjectId = Schema.Types.ObjectId,
    models = {};

module.exports = function (schema, options) {
    options = options || {};
    var primaryKeyName = options.primaryKeyName || '_id';

    var getHistoricalModel = function (model) {
        var connection = options.connection || model.constructor.collection.conn,
            name = options.name || model.constructor.modelName + 's_historical',
            primaryKeyType = (options.primaryKeyType || /* deprecated */ options.idType) || (model.constructor.schema.paths[primaryKeyName].options.type || ObjectId);

        if (!model.constructor.schema.paths[primaryKeyName]) {
            throw new Error('Historical error: Missing primary key `' + primaryKeyName + '` in schema `' + name + '`.');
        }

        models[model.constructor.modelName] = models[model.constructor.modelName] === undefined ?
            connection.model(name, new Schema({
                document: { type: primaryKeyType, index: true },
                timestamp: {type: Date, default: Date.now, index: true},
                diff: Schema.Types.Mixed
            })) : models[model.constructor.modelName];

        return models[model.constructor.modelName];
    };

    var read = function (o, p) {
        for (var i = 0, a = p.split('.'), l = a.length; i < l; i++) {
            o = o[a[i]];
        }
        return o;
    };

    var write = function (o, p, v) {
        for (var i = 0, a = p.split('.'); i < a.length - 1; i++) {
            var n = a[i];
            if (n in o) {
                o = o[n];
            } else {
                o[n] = {};
                o = o[n];
            }
        }
        o[a[a.length - 1]] = v;
    };

    schema.pre('save', function (next) {
        var me = this,
            HistoricalModel = getHistoricalModel(me),
            modified = _.uniq(me.modifiedPaths()),
            diff = {};

        modified.forEach(function (index) {
            var value = read(me, index);
            if (_.isObject(value) && !_.isArray(value)) {
                return;
            }
            if (value === undefined) {
                write(diff, index, null);
                return;
            }
            write(diff, index, value);
        });

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: diff
        });
        historical.save(next);
    });

    schema.pre('remove', function (next) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: null
        });
        historical.save(next);
    });

    schema.methods.historicalSnapshot = function (callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (me.modifiedPaths().length) {
            return callback(new Error('Historical error: Attempted to snapshot an unsaved/modified document.'));
        }

        var snapshot = me.toObject();
        delete snapshot[primaryKeyName];
        delete snapshot.__v;

        var historical = new HistoricalModel({
            document: me[primaryKeyName],
            diff: snapshot
        });
        historical.save(function (e) {
            if (e) {
                return callback(e);
            }
            return callback(null, me);
        });
    };

    schema.methods.historicalClear = function (callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        HistoricalModel.find({document: me[primaryKeyName]}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            me.historicalSnapshot(function (e) {
                if (e) {
                    return callback(e);
                }
                objs.forEach(function (obj) {
                    obj.remove();
                });
                return callback(null, me);
            });
        });
    };

    schema.methods.historicalRestore = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me),
            surrogate = {};

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        HistoricalModel.find({document: me[primaryKeyName], timestamp: {$lte: date}}, null, {sort: {timestamp: 1}}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            if (!objs) {
                return callback(null, null);
            }

            objs.forEach(function (obj) {
                if (!obj.diff) {
                    surrogate = null;
                }
                else {
                    surrogate = _.merge(surrogate, obj.diff);
                }
            });

            if (!surrogate) {
                return callback(null, null);
            }

            me.set(_.merge(me.toObject(), surrogate));
            return callback(null, me);
        });
    };

    schema.methods.historicalTrim = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        me.historicalRestore(date, function (e, obj) {
            if (e) {
                return callback(e);
            }
            if (!obj) {
                return callback(null, me);
            }
            HistoricalModel.remove({document: me[primaryKeyName], timestamp: {$lte: date}}, function (e) {
                if (e) {
                    return callback(e);
                }
                var trimmed = new HistoricalModel({
                    document: me[primaryKeyName],
                    diff: obj.toObject(),
                    timestamp: date
                });
                trimmed.save(function (e) {
                    if (e) {
                        return callback(e);
                    }
                    return callback(null, me);
                });
            });
        });
    };

    schema.methods.historicalDetails = function (date, callback) {
        var me = this,
            HistoricalModel = getHistoricalModel(me);

        callback = _.isFunction(callback) ? callback : function () {
        };

        if (!_.isDate(date) || date.getTime() > new Date().getTime()) {
            return callback(new Error('Historical error: Invalid date.'));
        }

        HistoricalModel.find({document: me[primaryKeyName], timestamp: {$lte: date}}, null, {sort: {timestamp: 1}}, function (e, objs) {
            if (e) {
                return callback(e);
            }
            return callback(null, objs);
        });
    };

    schema.methods.historical = function () {
        var me = this,
            action = null,
            date = new Date(),
            callback = function () {
            },
            args = Array.prototype.slice.call(arguments, 0, 3);

        if (_.isString(args[0])) {
            action = args[0];
        }

        if (_.isDate(args[1])) {
            date = args[1];
        }

        if (_.isFunction(args[args.length - 1])) {
            callback = args[args.length - 1];
        }

        switch (action) {
            case 'snapshot':
                me.historicalSnapshot(callback);
                break;
            case 'clear':
                me.historicalClear(callback);
                break;
            case 'restore':
                me.historicalRestore(date, callback);
                break;
            case 'trim':
                me.historicalTrim(date, callback);
                break;
            case 'history':
            case 'details':
            default:
                me.historicalDetails(date, callback);
        }
    };
};
<|endoftext|>


<commit_before><commit_msg>Add tests for main export<commit_after><|endoftext|>