<commit_before>var Cookie = require('./cookie');
var Token = require('./token');

var NoSes = module.exports = function (opts) {
	Object.defineProperty(this, 'tokenOpts', {
		value: { key: opts && opts.key || 'noKeySpecified' },
		enumerable: false,
		writable: false,
		configurable: false
	});

	this.opts = mixin(NoSes.DEFAULT_OPTS, opts);
	this.cookie = new Cookie(this.opts);
};

NoSes.DEFAULT_OPTS = {
	name: '_nsd',
	expires: 24*60*60,
	httpOnly: true,
	secure: false,
	maxAge: false,
	domain: false,
	path: false
};

NoSes.Cookie = Cookie;
NoSes.Token = Token;

NoSes.prototype.createExpiry = function () {
	var until = new Date();
	until.setSeconds(until.getSeconds() + this.opts.expires);
	return until;
};

NoSes.prototype.parse = function (req) {
	if (!req.headers.cookie) return req;
	var cookieData = this.cookie.parse(req.headers.cookie);
	if (cookieData) req._noses = Token.fromSecureString(cookieData, this.tokenOpts);
	return req;
};

NoSes.prototype.set = function (res, user, data) {
	var exp = this.createExpiry();
	var t = new Token(user, exp, data, this.tokenOpts);
	return this.cookie.write(res, t.toSecureString(), exp);
};

NoSes.prototype.createToken = function (user, data, cb) {
	var token = new Token(user, this.createExpiry, data, this.tokenOpts);
	if (!token.isValid) return cb(token._errors[0]);
	cb(null, token.toSecureString());
};

NoSes.prototype.parseToken = function (str, cb) {
	var token = Token.fromSecureString(str, this.tokenOpts);
	return cb((!token.isValid) ? token._errors[0] : null, token);
};

NoSes.parser = function (opts, cb) {
	var n = new NoSes(opts);
	return function (req, res, next) {
		req.noses = n;
		n.parse(req);
		return (typeof(cb) === 'function') ? cb(req, res, next) : (typeof(next) === 'function') ? next(req, res) : req;
	};
};

function mixin (a,b) {
	if (!b || typeof(b) !== 'object') b = {};
	var out = {};
	Object.keys(a).forEach(function (k) {
		out[k] = (b.hasOwnProperty(k)) ? b[k] : a[k];
	});
	return out;
}
<commit_msg>fix createExpiry call<commit_after>var Cookie = require('./cookie');
var Token = require('./token');

var NoSes = module.exports = function (opts) {
	Object.defineProperty(this, 'tokenOpts', {
		value: { key: opts && opts.key || 'noKeySpecified' },
		enumerable: false,
		writable: false,
		configurable: false
	});

	this.opts = mixin(NoSes.DEFAULT_OPTS, opts);
	this.cookie = new Cookie(this.opts);
};

NoSes.DEFAULT_OPTS = {
	name: '_nsd',
	expires: 24*60*60,
	httpOnly: true,
	secure: false,
	maxAge: false,
	domain: false,
	path: false
};

NoSes.Cookie = Cookie;
NoSes.Token = Token;

NoSes.prototype.createExpiry = function () {
	var until = new Date();
	until.setSeconds(until.getSeconds() + this.opts.expires);
	return until;
};

NoSes.prototype.parse = function (req) {
	if (!req.headers.cookie) return req;
	var cookieData = this.cookie.parse(req.headers.cookie);
	if (cookieData) req._noses = Token.fromSecureString(cookieData, this.tokenOpts);
	return req;
};

NoSes.prototype.set = function (res, user, data) {
	var exp = this.createExpiry();
	var t = new Token(user, exp, data, this.tokenOpts);
	return this.cookie.write(res, t.toSecureString(), exp);
};

NoSes.prototype.createToken = function (user, data, cb) {
	var token = new Token(user, this.createExpiry(), data, this.tokenOpts);
	if (!token.isValid) return cb(token._errors[0]);
	cb(null, token.toSecureString());
};

NoSes.prototype.parseToken = function (str, cb) {
	var token = Token.fromSecureString(str, this.tokenOpts);
	return cb((!token.isValid) ? token._errors[0] : null, token);
};

NoSes.parser = function (opts, cb) {
	var n = new NoSes(opts);
	return function (req, res, next) {
		req.noses = n;
		n.parse(req);
		return (typeof(cb) === 'function') ? cb(req, res, next) : (typeof(next) === 'function') ? next(req, res) : req;
	};
};

function mixin (a,b) {
	if (!b || typeof(b) !== 'object') b = {};
	var out = {};
	Object.keys(a).forEach(function (k) {
		out[k] = (b.hasOwnProperty(k)) ? b[k] : a[k];
	});
	return out;
}
<|endoftext|>


<commit_before>'use strict'

var test = require('tape')

test('NGN.DOM', function (t) {
  t.ok(typeof NGN.DOM.svg.update === 'function', 'SVG update exists.')

  var p = document.createElement('span')
  var hr = document.createElement('hr')
  var p2 = document.createElement('p')
  var sel = '#test1'
  var sel2 = 'body > span:first-of-type > p:last-of-type'

  hr.setAttribute('id', 'test1')
  p.appendChild(hr)
  p.appendChild(p2)

  document.body.appendChild(p)

  t.ok(NGN.DOM.findParent(sel) !== null, 'NGN.DOM.findParent() works.')

  NGN.DOM.destroy(document.querySelector(sel))

  t.ok(NGN.DOM.findParent(sel) === null, 'NGN.DOM.destroy() works.')

  var p3 = document.createElement('p')
  p.appendChild(p3)

  t.ok(NGN.DOM.indexOfParent(document.querySelector(sel2)) === 1, 'NGN.DOM.indexOfParent() works.')
  t.end()
})

test('NGN.DOM.svg Fragment Update', function (t) {
  try {
    NGN.DOM.svg.update('
<svg src="https://cdn.rawgit.com/gilbarbara/logos/master/logos/git.svg" class="test"></svg>
', function (content) {
      document.body.insertAdjacentHTML('beforeend', content)
      t.ok(document.body.querySelector('div#nestandtest > svg > g > path') !== null, 'Found generated SVG code in DOM Fragment Update.')
      t.end()
    })
  } catch (e) {
    t.fail('Did not update fragment: ' + e.message)
  }
})

test('NGN.DOM.svg Direct DOM update', function (t) {
  document.body.insertAdjacentHTML('beforeend', '<svg src="https://cdn.rawgit.com/gilbarbara/logos/master/logos/git.svg" class="test"></svg>')

  setTimeout(function () {
    NGN.DOM.svg.update(function () {
      t.ok(document.body.querySelector('svg > g > path') !== null, 'Found generated SVG code in direct DOM update.')
      t.end()
    })
  }, 300)
})

test('NGN.DOM.expandVoidHTMLTags', function (t) {
  var html = '
<svg class="test"><rect x="1"/></svg>
'
  var eHtml = NGN.DOM.expandVoidHTMLTags(html)

  t.ok(eHtml === '
<svg class="test"><rect x="1"></rect></svg>
')
  t.end()
})

test('NGN.DOM.guarantee', {
  timeout: 10000
}, function (t) {
  NGN.DOM.guarantee(document.body, '#testbutton', function (err, element) {
    t.pass('guarantee() callback invoked successfully')

    if (err) {
      t.fail(err.message)
    }

    t.ok(element.nodeName === 'BUTTON', 'Proper DOM element returned from guarantee().')

    var html = '<svg src="https://s3.amazonaws.com/uploads.hipchat.com/94386/693334/xCz24SJ9A3SFYUM/hamburger.svg" class="test"></svg>'
    NGN.DOM.svg.update(html, function (content) {
      NGN.DOM.guarantee(document.body, content, 8000, function (err2, el) {
        if (err2) {
          t.fail(err2.message)
        }

        t.pass('guarantee() invoked with text document fragment.')
        t.ok(document.body.querySelector('#guaranteeTest > svg > g > rect') !== null, 'Found generated SVG code in guaranteed DOM Fragment Update.')

        t.end()
      })

      document.body.insertAdjacentHTML('beforeend', content)
    })
  })

  setTimeout(function () {
    document.body.insertAdjacentHTML('beforeend', '<button id="testbutton"></button>')
  }, 300)
})

test('NGN.DOM.svg Warnings', function (t) {
  var src = '<svg src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"/>'

  setTimeout(function () {
    NGN.DOM.svg.update(src, function (content) {
      t.pass('No error thrown (just a warning).')
      t.end()
    })
  }, 700)
})

test('NGN.DOM.selectorOfElement', function (t) {
  document.body.insertAdjacentHTML('beforeend', '

test

')
  let selector = '#root > div:nth-child(3) > div:nth-child(2) > div:nth-child(1)'
  let element = document.body.querySelector(selector)

  t.ok(NGN.DOM.selectorOfElement(element) === selector, 'Proper selector generated.')
  t.end()
  //

  //

  //

  //

  //

  //

  //
test

  //

  //

  //

  //

  //

})
<commit_msg>Fixed tests for Safari.<commit_after>'use strict'

var test = require('tape')

test('NGN.DOM', function (t) {
  t.ok(typeof NGN.DOM.svg.update === 'function', 'SVG update exists.')

  var p = document.createElement('span')
  var hr = document.createElement('hr')
  var p2 = document.createElement('p')
  var sel = '#test1'
  var sel2 = 'body > span:first-of-type > p:last-of-type'

  hr.setAttribute('id', 'test1')
  p.appendChild(hr)
  p.appendChild(p2)

  document.body.appendChild(p)

  t.ok(NGN.DOM.findParent(sel) !== null, 'NGN.DOM.findParent() works.')

  NGN.DOM.destroy(document.querySelector(sel))

  t.ok(NGN.DOM.findParent(sel) === null, 'NGN.DOM.destroy() works.')

  var p3 = document.createElement('p')
  p.appendChild(p3)

  t.ok(NGN.DOM.indexOfParent(document.querySelector(sel2)) === 1, 'NGN.DOM.indexOfParent() works.')
  t.end()
})

test('NGN.DOM.svg Fragment Update', function (t) {
  try {
    NGN.DOM.svg.update('
<svg src="https://cdn.rawgit.com/gilbarbara/logos/master/logos/git.svg" class="test"></svg>
', function (content) {
      document.body.insertAdjacentHTML('beforeend', content)
      t.ok(document.body.querySelector('div#nestandtest > svg > g > path') !== null, 'Found generated SVG code in DOM Fragment Update.')
      t.end()
    })
  } catch (e) {
    t.fail('Did not update fragment: ' + e.message)
  }
})

test('NGN.DOM.svg Direct DOM update', function (t) {
  document.body.insertAdjacentHTML('beforeend', '<svg src="https://cdn.rawgit.com/gilbarbara/logos/master/logos/git.svg" class="test"></svg>')

  setTimeout(function () {
    NGN.DOM.svg.update(function () {
      t.ok(document.body.querySelector('svg > g > path') !== null, 'Found generated SVG code in direct DOM update.')
      t.end()
    })
  }, 300)
})

test('NGN.DOM.expandVoidHTMLTags', function (t) {
  var html = '
<svg class="test"><rect x="1"/></svg>
'
  var eHtml = NGN.DOM.expandVoidHTMLTags(html)

  t.ok(eHtml === '
<svg class="test"><rect x="1"></rect></svg>
')
  t.end()
})

test('NGN.DOM.guarantee', {
  timeout: 10000
}, function (t) {
  NGN.DOM.guarantee(document.body, '#testbutton', function (err, element) {
    t.pass('guarantee() callback invoked successfully')

    if (err) {
      t.fail(err.message)
    }

    t.ok(element.nodeName === 'BUTTON', 'Proper DOM element returned from guarantee().')

    var html = '<svg src="https://s3.amazonaws.com/uploads.hipchat.com/94386/693334/xCz24SJ9A3SFYUM/hamburger.svg" class="test"></svg>'
    NGN.DOM.svg.update(html, function (content) {
      NGN.DOM.guarantee(document.body, content, 8000, function (err2, el) {
        if (err2) {
          t.fail(err2.message)
        }

        t.pass('guarantee() invoked with text document fragment.')
        t.ok(document.body.querySelector('#guaranteeTest > svg > g > rect') !== null, 'Found generated SVG code in guaranteed DOM Fragment Update.')

        t.end()
      })

      document.body.insertAdjacentHTML('beforeend', content)
    })
  })

  setTimeout(function () {
    document.body.insertAdjacentHTML('beforeend', '<button id="testbutton"></button>')
  }, 300)
})

test('NGN.DOM.svg Warnings', function (t) {
  var src = '<svg src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"/>'

  setTimeout(function () {
    NGN.DOM.svg.update(src, function (content) {
      t.pass('No error thrown (just a warning).')
      t.end()
    })
  }, 700)
})

test('NGN.DOM.selectorOfElement', function (t) {
  document.body.insertAdjacentHTML('beforeend', '

test

')
  var selector = '#root > div:nth-child(3) > div:nth-child(2) > div:nth-child(1)'
  var element = document.body.querySelector(selector)

  t.ok(NGN.DOM.selectorOfElement(element) === selector, 'Proper selector generated.')
  t.end()
  //

  //

  //

  //

  //

  //

  //
test

  //

  //

  //

  //

  //

})
<|endoftext|>


<commit_before>var util = require("./util");
var DataType = require("./DataType");
var JSContext = require("./JSContext");
var PNaClContext = require("./PNaClContext");
var WebCLContext = require("./WebCLContext");

var connect = function(backend, callback) {
	if (typeof callback === "undefined") {
		callback = backend;
		backend = undefined;
	}
	if (typeof backend == "undefined") {
		backend = getDefaultBackend();
	}
	if (backend == "javascript") {
		return new JSContext(callback);
	} else if (backend == "pnacl") {
		return new PNaClContext(callback);
	} else if (backend == "webcl") {
		return new WebCLContext(callback);
	} else {
		throw new Error("Unsupported backend: " + backend);
	}
}

var getDefaultBackend = function() {
	if (hasFeature("webcl")) {
		return "webcl";
	} else if (hasFeature("pnacl")) {
		return "pnacl";
	} else {
		return "javascript";
	}
}

var getSupportedBackends = function() {
	var backends = [];
	if (hasFeature("webcl")) {
		backends.push("webcl");
	}
	if (hasFeature("pnacl")) {
		backends.push("pnacl");
	}
	if (hasFeature("asm.js")) {
		backends.push("asm.js");
	}
	backends.push("javascript");
	return backends;
}

var hasFeature = function(name) {
	switch (name) {
		case "asm.js":
			try {
				var userAgent = window.navigator.userAgent;
				var userAgentComponents = userAgent.split(/\s+/);
				var firefoxRegexp = /[Ff]irefox\/(\d+)/g;
				for (component in userAgentComponents) {
					var match = firefoxRegexp.exec(component);
					if (match != null) {
						var firefoxVersion = parseInt(match[0]);
						return firefoxVersion >= 29;
					}
				}
				return false;
			} catch (e) {
				return false;
			}
		case "simd.js":
			return (typeof SIMD !== "undefined");
		case "webgl":
			try {
				var canvas = document.createElement("canvas");
				try {
					if (canvas.getContext("webgl") != null) {
						return true;
					}
				} catch (e) {
				}
				try {
					if (canvas.getContext("experimental-webgl") != null) {
						return true;
					}
				} catch (e) {
				}
			} catch (e) {
			}
			return false;
		case "webcl":
			if (typeof webcl !== "undefined") {
				try {
					var platforms = webcl.getPlatforms();
					return platforms.length >= 1;
				} catch (e) {
					return false;
				}
			} else if (typeof WebCL !== "undefined") {
				try {
					var webcl = new WebCL();
					var platforms = webcl.getPlatforms();
					return platforms.length >= 1;
				} catch (e) {
					return false;
				}
			} else {
				return false;
			}
		case "pnacl":
			try {
				return (typeof navigator.mimeTypes["application/x-pnacl"]) !== "undefined";
			} catch (e) {
				return false;
			}
		case "nacl":
			try {
				return (typeof navigator.mimeTypes["application/x-nacl"]) !== "undefined";
			} catch (e) {
				return false;
			}
		default:
			throw new Error("Unknown feature: " + name);
	}
}

exports.connect = connect;
exports.hasFeature = hasFeature;
exports.getDefaultBackend = getDefaultBackend;
exports.getSupportedBackends = getSupportedBackends;
exports.DataType = DataType;
<commit_msg>Docs: document the numjs module<commit_after>/**
 * Provides information and support functions
 *
 * @class numjs
 */

var util = require("./util");
var DataType = require("./DataType");
var JSContext = require("./JSContext");
var PNaClContext = require("./PNaClContext");
var WebCLContext = require("./WebCLContext");

/**
 * Initializes a computational context.
 *
 * @static
 * @method connect
 * @async
 *
 * @param {String} [backend] - A string identifier for the backend to use. The following values are supported:
 *
 *

 *

 *             Backend Identifier
 *             Interpretation
 *

 *

 *             "javascript"
 *             JavaScript backend. Works in all browsers and Node.js, but can not deliver optimal performance.
 *

 *

 *             "pnacl"
 *             Portable Native Client (PNaCl) backend. Works in Chromium-based browsers. Can accelerate computations through the use of advanced CPU optimization technologies, such as multi-threading and SIMD instructions.
 *

 *

 *             "webcl"
 *             WebCL backend. Works in browsers and Node.js when a WebCL plugin is available. Can use full power of CPUs and GPUs to accelerate computations.
 *

 *

 *
 * @param {Function} callback - A callback function that is called when the backend finish initialization.
 * @param {Context} callback.context - A ready to use computational context.
 */
var connect = function(backend, callback) {
	if (typeof callback === "undefined") {
		callback = backend;
		backend = undefined;
	}
	if (typeof backend == "undefined") {
		backend = getDefaultBackend();
	}
	if (backend == "javascript") {
		return new JSContext(callback);
	} else if (backend == "pnacl") {
		return new PNaClContext(callback);
	} else if (backend == "webcl") {
		return new WebCLContext(callback);
	} else {
		throw new Error("Unsupported backend: " + backend);
	}
}

/**
 * Detects the optimal backend supported by the browser or JavaScript engine.
 *
 * @static
 * @method getDefaultBackend
 *
 * @return {String} - Default backend identifier from the following table:
 *
 *

 *

 *             Backend Identifier
 *             Interpretation
 *

 *

 *             "javascript"
 *             JavaScript backend. Works in all browsers and Node.js, but can not deliver optimal performance.
 *

 *

 *             "asmjs"
 *             Asm.js backend. Works in Firefox 29 and later. Can accelerate computations with a limited use of native CPU instructions.
 *

 *

 *             "pnacl"
 *             Portable Native Client (PNaCl) backend. Works in Chromium-based browsers. Can accelerate computations through the use of advanced CPU optimization technologies, such as multi-threading and SIMD instructions.
 *

 *

 *             "webcl"
 *             WebCL backend. Works in browsers and Node.js when a WebCL plugin is available. Can use full power of CPUs and GPUs to accelerate computations.
 *

 *

 */
var getDefaultBackend = function() {
	if (hasFeature("webcl")) {
		return "webcl";
	} else if (hasFeature("pnacl")) {
		return "pnacl";
	} else {
		return "javascript";
	}
}

/**
 * Detects which backends are supported by the system.
 *
 * @static
 * @method getSupportedBackends
 *
 * @return {String[]} - An array of supported backend identifiers in priority order (prioritized backends first). The following identifiers could be present:
 *
 *

 *

 *             Backend Identifier
 *             Interpretation
 *

 *

 *             "javascript"
 *             JavaScript backend. Works in all browsers and Node.js, but can not deliver optimal performance.
 *

 *

 *             "asmjs"
 *             Asm.js backend. Works in Firefox 29 and later. Can accelerate computations with a limited use of native CPU instructions.
 *

 *

 *             "pnacl"
 *             Portable Native Client (PNaCl) backend. Works in Chromium-based browsers. Can accelerate computations through the use of advanced CPU optimization technologies, such as multi-threading and SIMD instructions.
 *

 *

 *             "webcl"
 *             WebCL backend. Works in browsers and Node.js when a WebCL plugin is available. Can use full power of CPUs and GPUs to accelerate computations.
 *

 *

 */
var getSupportedBackends = function() {
	var backends = [];
	if (hasFeature("webcl")) {
		backends.push("webcl");
	}
	if (hasFeature("pnacl")) {
		backends.push("pnacl");
	}
	if (hasFeature("asm.js")) {
		backends.push("asm.js");
	}
	backends.push("javascript");
	return backends;
}

/**
 * Detects whether the requested computing feature is available
 *
 * @static
 * @method hasFeature
 *
 * @param {String} name - an identifier of the optional feature to detect. The following identifiers are supported:
 *
 *

 *

 *             Feature Identifier
 *             Interpretation
 *

 *

 *             "asm.js"
 *             Detect if the JavaScript engine recognizes Asm.js directive.
 *

 *

 *             "simd.js"
 *             Detect if the JavaScript engine provide SIMD.float32x4, SIMD.int32x4, Float32x4Array, and Int32x4Array of SIMD.js
 *

 *

 *             "webgl"
 *             Detect if the browser supports WebGL (either experimental or stable implementation)
 *

 *

 *             "webcl"
 *             Detect if the browser supports WebCL
 *

 *

 *             "pnacl"
 *             Detect if Portable Native Client (PNaCl) is supported and enabled
 *

 *

 *             "nacl"
 *             Detect if Native Client (NaCl) is supported and enabled
 *

 *

 *
 * @return {Boolean} true if the feature is supported, false otherwise
 */
var hasFeature = function(name) {
	switch (name) {
		case "asm.js":
			try {
				var userAgent = window.navigator.userAgent;
				var userAgentComponents = userAgent.split(/\s+/);
				var firefoxRegexp = /[Ff]irefox\/(\d+)/g;
				for (component in userAgentComponents) {
					var match = firefoxRegexp.exec(component);
					if (match != null) {
						var firefoxVersion = parseInt(match[0]);
						return firefoxVersion >= 29;
					}
				}
				return false;
			} catch (e) {
				return false;
			}
		case "simd.js":
			return (typeof SIMD !== "undefined");
		case "webgl":
			try {
				var canvas = document.createElement("canvas");
				try {
					if (canvas.getContext("webgl") != null) {
						return true;
					}
				} catch (e) {
				}
				try {
					if (canvas.getContext("experimental-webgl") != null) {
						return true;
					}
				} catch (e) {
				}
			} catch (e) {
			}
			return false;
		case "webcl":
			if (typeof webcl !== "undefined") {
				try {
					var platforms = webcl.getPlatforms();
					return platforms.length >= 1;
				} catch (e) {
					return false;
				}
			} else if (typeof WebCL !== "undefined") {
				try {
					var webcl = new WebCL();
					var platforms = webcl.getPlatforms();
					return platforms.length >= 1;
				} catch (e) {
					return false;
				}
			} else {
				return false;
			}
		case "pnacl":
			try {
				return (typeof navigator.mimeTypes["application/x-pnacl"]) !== "undefined";
			} catch (e) {
				return false;
			}
		case "nacl":
			try {
				return (typeof navigator.mimeTypes["application/x-nacl"]) !== "undefined";
			} catch (e) {
				return false;
			}
		default:
			throw new Error("Unknown feature: " + name);
	}
}

exports.connect = connect;
exports.hasFeature = hasFeature;
exports.getDefaultBackend = getDefaultBackend;
exports.getSupportedBackends = getSupportedBackends;
exports.DataType = DataType;
<|endoftext|>


<commit_before>/*
Copyright 2015 Province of British Columbia

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
*/

'use strict'
var async = require('async')
var request = require('request')
var config = require('config')
var logger = require('../../common/logging.js').logger
var yaml = require('js-yaml')
var crypto = require('crypto')
var clone = require('clone')
var merge = require('merge')
var db = require('../models/db')
var _ = require('lodash')
var Q = require('q')

var getProgramsFromArray = function (programList, success, error) {
  async.concat(programList, getPrograms, function (err, results) {
    if (err) error(err)
    else {

      // filter out invisible
      var i = 0
      while (i < results.length) {
        var program = results[i]
        if (program.visible !== "yes" &&
          program.visible !== "y" &&
          program.visible !== "true") {

          // remove from result
          results.splice(i, 1)

          // decrement the counter
          i--
        }
        i++
      }
      success(results)
    }
  })
}

module.exports = function (app, db, passport) {

  app.get('/api/programs/', function (req, res) {

    getProgramsFromArray(config.programs, function (results) {
      var body = {
        "programs": results
      }
      res.send(body)
    }, function (error) {
      res.sendStatus(500)
    })
  })
  app.get('/api/programs/name/:title', function (req, res) {
    if (!req.params.title) {
      res.send(400, "Missing url title.")
      return
    }

    db.getProgramByName(req.params.title).then(function (data) {
      getProgramDetails(data, function (error, result) {
        if (error) {
          res.send(500)
        }
        res.send(_.merge({}, result, data))
      })
    })
  })

  app.patch('/api/programs/:id', function (req, res) {
    if (req.user.siteAdmin) {
      db.updateProgram(req.params.id, req.body).then(function (data) {
        res.end()
      })
      return
    }

    db.getProgram(req.params.id).then(function (program) {
      if (program.editors && program.editors.indexOf(req.user._id) >= 0) {
        db.updateProgram(req.params.id, req.body).then(function (data) {
          res.end()
        })
      }
    })
  })
}

function getPrograms(program, callback) {

  if (program.type === "github-file") {
    getGitHubFileProgram(program, callback)
  } else {
    logger.error("Configuration error, unknown program type: " + program.type)
  }

}

function getGitHubFileProgram(ghConfig, callback) {
  var options = {
    url: 'https://api.github.com/' + ghConfig.url + "?client_id=" + config.github.clientID + "&client_secret=" + config.github.clientSecret,
    headers: {
      'User-Agent': config.github.clientApplicationName
    }
  }
  request(options, function (error, response, body) {
    if (!error &&
      typeof response !== 'undefined' &&
      response.statusCode === 200) {

      // parse out the yaml from content block
      var json = JSON.parse(body)
      var decodedContent = new Buffer(json.content, 'base64').toString('ascii')
      var programYaml

      try {
        programYaml = yaml.safeLoad(decodedContent)

      } catch (requestError) {
        var message = 'Error while parsing yaml program file from: ' + options.url + '. message: ' + requestError.message
        logger.error(message)
        return callback(message)
      }
      // remove extraneous info from result
      async.concat(programYaml, parseGitHubFileResults, function (err, results) {
        return callback(err, results)
      })
    } else {
      logger.error('Error while fetching GitHub content: %s. response: %s. body: %s', error, response, body)
      return callback(error)
    }
  })
}

function parseGitHubFileResults(result, callback) {
  var transformed = {
    "title": result.title,
    "description": result.description,
    "owner": result.owner,
    "logo": result.logo,
    "tags": [],
    "url": result.url,
    "id": result.id,
    "visible": result.visible
  }

  if (result.tags) {
    var i = 0
    while (i < result.tags.length) {
      transformed.tags[i] = {
        "display_name": result.tags[i]
      }
      transformed.tags[i].id = crypto.createHash('md5').update(result.tags[i]).digest("hex")
      i++
    }
  }
  return callback(null, transformed)

}

function getProgramDetails(progData, callback) {
  var deferred = Q.defer()
    // Call github for stats
  if (!progData.githubUrl) {
    setTimeout(function () {
      deferred.resolve({})
    }, 0)
    return deferred.promise.nodeify(callback)
  }
  async.concat(['/stats/contributors', '/issues'], function (item, cb) {
    var options = {
      url: 'https://api.github.com/repos/' + progData.githubUrl.substr(progData.githubUrl.indexOf('github.com') + 11) + item + "?client_id=" + config.github.clientID + "&client_secret=" + config.github.clientSecret,
      headers: {
        'User-Agent': config.github.clientApplicationName
      }
    }
    request(options, function (error, response, body) {
      if (!error &&
        typeof response !== 'undefined' &&
        response.statusCode === 200) {
        return cb(null, body)
      } else {
        logger.error('Error while fetching GitHub content: %s. response: %s. body: %s', error, response, body)
        return cb(error)
      }
    })
  }, function (err, resArr) {
    if (err) return deferred.reject(err)
    var issuesPrArr = JSON.parse(resArr[1])
    var issuesPrCnt = issuesPrArr.length
    var prCnt = _.reduce(issuesPrArr, function (result, item) {
      return result + ((item.pull_request) ? 1 : 0)
    }, 0)
    var res = {
      contributors: JSON.parse(resArr[0]).length,
      issues: issuesPrCnt - prCnt,
      prs: prCnt
    }
    deferred.resolve(res)
  })
  return deferred.promise.nodeify(callback)
}
<commit_msg>changed async.concat  to async.parallel b/c former doesn't preserve order<commit_after>/*
Copyright 2015 Province of British Columbia

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
*/

'use strict'
var async = require('async')
var request = require('request')
var config = require('config')
var logger = require('../../common/logging.js').logger
var yaml = require('js-yaml')
var crypto = require('crypto')
var clone = require('clone')
var merge = require('merge')
var db = require('../models/db')
var _ = require('lodash')
var Q = require('q')

var getProgramsFromArray = function (programList, success, error) {
  async.concat(programList, getPrograms, function (err, results) {
    if (err) error(err)
    else {

      // filter out invisible
      var i = 0
      while (i < results.length) {
        var program = results[i]
        if (program.visible !== "yes" &&
          program.visible !== "y" &&
          program.visible !== "true") {

          // remove from result
          results.splice(i, 1)

          // decrement the counter
          i--
        }
        i++
      }
      success(results)
    }
  })
}

module.exports = function (app, db, passport) {

  app.get('/api/programs/', function (req, res) {

    getProgramsFromArray(config.programs, function (results) {
      var body = {
        "programs": results
      }
      res.send(body)
    }, function (error) {
      res.sendStatus(500)
    })
  })
  app.get('/api/programs/name/:title', function (req, res) {
    if (!req.params.title) {
      res.send(400, "Missing url title.")
      return
    }

    db.getProgramByName(req.params.title).then(function (data) {
      getProgramDetails(data, function (error, result) {
        if (error) {
          res.send(500)
        }
        res.send(_.merge({}, result, data))
      })
    })
  })

  app.patch('/api/programs/:id', function (req, res) {
    if (req.user.siteAdmin) {
      db.updateProgram(req.params.id, req.body).then(function (data) {
        res.end()
      })
      return
    }

    db.getProgram(req.params.id).then(function (program) {
      if (program.editors && program.editors.indexOf(req.user._id) >= 0) {
        db.updateProgram(req.params.id, req.body).then(function (data) {
          res.end()
        })
      }
    })
  })
}

function getPrograms(program, callback) {

  if (program.type === "github-file") {
    getGitHubFileProgram(program, callback)
  } else {
    logger.error("Configuration error, unknown program type: " + program.type)
  }

}

function getGitHubFileProgram(ghConfig, callback) {
  var options = {
    url: 'https://api.github.com/' + ghConfig.url + "?client_id=" + config.github.clientID + "&client_secret=" + config.github.clientSecret,
    headers: {
      'User-Agent': config.github.clientApplicationName
    }
  }
  request(options, function (error, response, body) {
    if (!error &&
      typeof response !== 'undefined' &&
      response.statusCode === 200) {

      // parse out the yaml from content block
      var json = JSON.parse(body)
      var decodedContent = new Buffer(json.content, 'base64').toString('ascii')
      var programYaml

      try {
        programYaml = yaml.safeLoad(decodedContent)

      } catch (requestError) {
        var message = 'Error while parsing yaml program file from: ' + options.url + '. message: ' + requestError.message
        logger.error(message)
        return callback(message)
      }
      // remove extraneous info from result
      async.concat(programYaml, parseGitHubFileResults, function (err, results) {
        return callback(err, results)
      })
    } else {
      logger.error('Error while fetching GitHub content: %s. response: %s. body: %s', error, response, body)
      return callback(error)
    }
  })
}

function parseGitHubFileResults(result, callback) {
  var transformed = {
    "title": result.title,
    "description": result.description,
    "owner": result.owner,
    "logo": result.logo,
    "tags": [],
    "url": result.url,
    "id": result.id,
    "visible": result.visible
  }

  if (result.tags) {
    var i = 0
    while (i < result.tags.length) {
      transformed.tags[i] = {
        "display_name": result.tags[i]
      }
      transformed.tags[i].id = crypto.createHash('md5').update(result.tags[i]).digest("hex")
      i++
    }
  }
  return callback(null, transformed)

}

function getProgramDetails(progData, callback) {
  var deferred = Q.defer()
    // Call github for stats
  if (!progData.githubUrl) {
    setTimeout(function () {
      deferred.resolve({})
    }, 0)
    return deferred.promise.nodeify(callback)
  }

  var getGitHubStats = function (item, cb) {
    var options = {
      url: 'https://api.github.com/repos/' + progData.githubUrl.substr(progData.githubUrl.indexOf('github.com') + 11) + item + "?client_id=" + config.github.clientID + "&client_secret=" + config.github.clientSecret,
      headers: {
        'User-Agent': config.github.clientApplicationName
      }
    }
    request(options, function (error, response, body) {
      if (!error &&
        typeof response !== 'undefined' &&
        response.statusCode === 200) {
        return cb(null, body)
      } else {
        logger.error('Error while fetching GitHub content: %s. response: %s. body: %s', error, response, body)
        return cb(error)
      }
    })
  }

  async.parallel([function (cb) {
      getGitHubStats('/stats/contributors', cb)
    },
                function (cb) {
      getGitHubStats('/issues', cb)
    }], function (err, resArr) {
    if (err) return deferred.reject(err)
    var issuesPrArr = JSON.parse(resArr[1])
    var issuesPrCnt = issuesPrArr.length
    var prCnt = _.reduce(issuesPrArr, function (result, item) {
      return result + ((item.pull_request) ? 1 : 0)
    }, 0)
    var res = {
      contributors: JSON.parse(resArr[0]).length,
      issues: issuesPrCnt - prCnt,
      prs: prCnt
    }
    deferred.resolve(res)
  })
  return deferred.promise.nodeify(callback)
}
<|endoftext|>


<commit_before>// A simple test to verify a visible window is opened with a title
import { Application } from 'spectron';
import path from 'path';
import { expect } from 'chai';

const app = new Application({
  path: require('electron-prebuilt'),
  args: [
    path.join(__dirname, '..', 'app')
  ],
  waitTimeout: 2000
});

const delay = time => new Promise(resolve => setTimeout(resolve, time));

describe('screenshot', function testApp() {
  this.retries(3);

  // Constructs url similar to file:///Users/john/popcorn-desktop-experimental/app/app.html#/${url}
  const navigate = url => this.app.client.url(`file://${process.cwd()}/app/app.html#/${url}`);

  const findCardList = () => this.app.client.waitForVisible('.CardList');
  const findCard = () => this.app.client.waitForVisible('.Card');
  const findMovie = () => this.app.client.waitForVisible('.Movie');

  before(async done => {
    try {
      this.app = await app.start();
      done();
    } catch (error) {
      done(error);
    }
  });

  after(() => {
    if (this.app && this.app.isRunning()) {
      return this.app.stop();
    }
  });

  describe('main window', () => {
    it('should open window', async done => {
      try {
        const title = await this.app.client.getTitle();
        expect(title).to.equal('Popcorn Time');
        done();
      } catch (error) {
        done(error);
      }
    });
  });

  describe('HomePage', () => {
    beforeEach(async done => {
      try {
        await navigate('');
        await delay(2000);
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should display CardList', async function cardListTest(done) {
      try {
        const cardListIsDisplayed = await findCardList().isVisible('.CardList');
        const cardIsDisplayed = await findCard().isVisible('.CardList');
        expect(cardListIsDisplayed).to.equal(true);
        expect(cardIsDisplayed).to.equal(true);
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should search items', async done => {
      try {
        await this.app.client
          .setValue('.navbar input', 'harry potter')
          .click('.navbar button');

        await delay(2000); // await search results

        const movieTitles = await this.app.client.getText('.Card .Card--title');
        expect(movieTitles[0]).to.include('Harry Potter');
        expect(movieTitles[1]).to.include('Harry Potter');
        expect(movieTitles[2]).to.include('Harry Potter');
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should navigate to item on CardList click', async done => {
      try {
        const isVisible = await this.app.client
          .click('.Card--overlay:first-child')
          .waitForVisible('.Movie')
          .isVisible('.Movie');
        expect(isVisible).to.equal(true);

        await delay(2000);

        const [titleText] = await this.app.client.getText('.Movie h1');
        expect(titleText).to.be.a('string');
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should navigate between movies and shows', async done => {
      try {
        await this.app.client.click('.nav-item:nth-child(2) .nav-link');
        await delay(2000);
        const cardLinks = await this.app.client.getAttribute('.Card a', 'href');
        expect(cardLinks[0]).to.include('item/shows');
        done();
      } catch (error) {
        done(error);
      }
    });
  });

  describe('MoviePage', () => {
    beforeEach(async done => {
      try {
        // navigate to Game of thrones
        await navigate('item/shows/tt0944947');
        await this.app.client.waitForVisible('.Movie');
        await delay(2000);
        done();
      } catch (error) {
        done(error);
      }
    });
  });
});
<commit_msg>add homepage screenshot testing<commit_after>// A simple test to verify a visible window is opened with a title
import { Application } from 'spectron';
import path from 'path';
import { expect } from 'chai';

const app = new Application({
  path: require('electron-prebuilt'),
  args: [
    path.join(__dirname, '..', 'app')
  ],
  waitTimeout: 2000
});

const delay = time => new Promise(resolve => setTimeout(resolve, time));

describe('screenshot', function testApp() {
  this.retries(3);

  // Constructs url similar to file:///Users/john/popcorn-desktop-experimental/app/app.html#/${url}
  const navigate = url => this.app.client.url(`file://${process.cwd()}/app/app.html#/${url}`);

  const findCardList = () => this.app.client.waitForVisible('.CardList');
  const findCard = () => this.app.client.waitForVisible('.Card');
  const findMovie = () => this.app.client.waitForVisible('.Movie');

  before(async done => {
    try {
      this.app = await app.start();
      done();
    } catch (error) {
      done(error);
    }
  });

  after(() => {
    if (this.app && this.app.isRunning()) {
      return this.app.stop();
    }
  });

  describe('main window', () => {
    it('should open window', async done => {
      try {
        const title = await this.app.client.getTitle();
        expect(title).to.equal('Popcorn Time');
        done();
      } catch (error) {
        done(error);
      }
    });
  });

  describe('HomePage', () => {
    beforeEach(async done => {
      try {
        await navigate('');
        await delay(2000);
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should display CardList', async function cardListTest(done) {
      try {
        const cardListIsDisplayed = await findCardList().isVisible('.CardList');
        const cardIsDisplayed = await findCard().isVisible('.CardList');
        expect(cardListIsDisplayed).to.equal(true);
        expect(cardIsDisplayed).to.equal(true);
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should search items', async done => {
      try {
        await this.app.client
          .setValue('.navbar input', 'harry potter')
          .click('.navbar button');

        await delay(2000); // await search results

        const movieTitles = await this.app.client.getText('.Card .Card--title');
        expect(movieTitles[0]).to.include('Harry Potter');
        expect(movieTitles[1]).to.include('Harry Potter');
        expect(movieTitles[2]).to.include('Harry Potter');
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should navigate to item on CardList click', async done => {
      try {
        const isVisible = await this.app.client
          .click('.Card--overlay:first-child')
          .waitForVisible('.Movie')
          .isVisible('.Movie');
        expect(isVisible).to.equal(true);

        await delay(2000);

        const [titleText] = await this.app.client.getText('.Movie h1');
        expect(titleText).to.be.a('string');
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should navigate between movies and shows', async done => {
      try {
        await this.app.client.click('.nav-item:nth-child(2) .nav-link');
        await delay(2000);
        const cardLinks = await this.app.client.getAttribute('.Card a', 'href');
        expect(cardLinks[0]).to.include('item/shows');
        done();
      } catch (error) {
        done(error);
      }
    });
  });

  describe('MoviePage', () => {
    beforeEach(async done => {
      try {
        // navigate to Game of thrones
        await navigate('item/shows/tt0944947');
        await this.app.client.waitForVisible('.Movie');
        await delay(2000);
        done();
      } catch (error) {
        done(error);
      }
    });
  });

  describe('Screenshots', () => {
    beforeEach(async done => {
      try {
        // navigate to homepage (Movie Page)
        await navigate('');
        await this.app.client.waitForVisible('.Movie');
        this.app.browserWindow.capturePage().then(imageBuffer => {
          fs.writeFile('./screenshots/page.png', imageBuffer);
        });
        done();
      } catch (error) {
        done(error);
      }
    });

    it('should match the control homepage screenshot', async done => {
      try {
        const diff = resemble('./screenshots/page.png')
          .compareTo('./screenshots/base-homepage.png')
          .ignoreColors()
          .onComplete(data => {
            console.log(data.misMatchPercentage);
            return data.misMatchPercentage;
          });
        await delay(2000);
        expect(diff).to.equal(100);
        done();
      } catch (error) {
        done(error);
      }
    });
  });
});
<|endoftext|>


<commit_before>'use strict';
var gulp = require('gulp'),
	sass = require('gulp-sass'),
	del = require('del');

gulp.task('sass', function () {
	gulp.src('./src/scss/*.scss')
		.pipe(sass())
		.pipe(gulp.dest('./dist/css'));
});

gulp.task('svg', function () {
	gulp.src('./src/icons/*.svg')
		.pipe(gulp.dest('./dist/icons'));
});

gulp.task('update-static', function () {
	del('./gh-pages/vendor/wikia-style-guide/dist');
	gulp.src('./dist/**/*')
		.pipe(gulp.dest('./gh-pages/vendor/wikia-style-guide/dist'));
});

gulp.task('watch', function () {
	gulp.watch('./src/**/*').on('change', function (change) {
		if (change.path.match('scss')) {
			gulp.start('sass');
		} else if (change.path.match('svg')) {
			gulp.start('svg');
		}
		gulp.start('update-static');
	});
});
<commit_msg>send sass compile errors to console<commit_after>'use strict';
var gulp = require('gulp'),
	sass = require('gulp-sass'),
	del = require('del');

gulp.task('sass', function () {
	gulp.src('./src/scss/**/*.scss')
		.pipe(sass({
			errLogToConsole: true
		}))
		.pipe(gulp.dest('./dist/css'));
});

gulp.task('svg', function () {
	gulp.src('./src/icons/*.svg')
		.pipe(gulp.dest('./dist/icons'));
});

gulp.task('update-static', function () {
	del('./gh-pages/vendor/wikia-style-guide/dist');
	gulp.src('./dist/**/*')
		.pipe(gulp.dest('./gh-pages/vendor/wikia-style-guide/dist'));
});

gulp.task('watch', function () {
	gulp.watch('./src/**/*').on('change', function (change) {
		if (change.path.match('scss')) {
			gulp.start('sass');
		} else if (change.path.match('svg')) {
			gulp.start('svg');
		}
		gulp.start('update-static');
	});
});
<|endoftext|>


<commit_before>const moveSelectionBy = require('./transforms/moveSelectionBy');
const insertRow = require('./transforms/insertRow');

/**
 * Select all text of current block.
 * @param {Slate.Transform} transform
 * @return {Slate.Transform}
 */
function selectAllText(transform) {
    const { state } = transform;
    const { startBlock } = state;

    return transform
        .moveToOffsets(0)
        .extendForward(startBlock.length);
}

/**
 * Pressing "Tab" moves the cursor to the next cell
 * and select the whole text
 */
function onTab(event, data, state, opts) {
    const direction = (data.isShift ? -1 : +1);
    const transform = state.transform();
    let newTransform = moveSelectionBy(opts, transform, direction, 0);

    // Is outside the table
    if (newTransform === transform) {
        if (direction > 0) {
            newTransform = insertRow(opts, transform);
        } else {
            newTransform = insertRow(opts, transform, 0);
        }

        newTransform = moveSelectionBy(opts, newTransform, direction, 0);
    }

    event.preventDefault();

    // We have to apply the transform so that "selectAllText"
    // can have access to an updated "startBlock"
    newTransform = newTransform
        .apply()
        .transform();

    return selectAllText(newTransform)
        .apply();
}

module.exports = onTab;
<commit_msg>Fix onTab for slate 0.14.x<commit_after>const TablePosition = require('./TablePosition');
const moveSelectionBy = require('./transforms/moveSelectionBy');
const insertRow = require('./transforms/insertRow');

/**
 * Select all text of current block.
 * @param {Slate.Transform} transform
 * @return {Slate.Transform}
 */
function selectAllText(transform) {
    const { state } = transform;
    const { startBlock } = state;

    return transform
        .moveToOffsets(0)
        .extendForward(startBlock.length);
}

/**
 * Pressing "Tab" moves the cursor to the next cell
 * and select the whole text
 */
function onTab(event, data, state, opts) {
    event.preventDefault();
    const direction = (data.isShift ? -1 : +1);
    let transform = state.transform();

    // Create new row if needed
    const { startBlock } = state;
    const pos = TablePosition.create(state, startBlock);
    if (pos.isFirstCell() && direction === -1) {
        transform = insertRow(opts, transform, 0);
    } else if (pos.isLastCell() && direction === 1) {
        transform = insertRow(opts, transform);
    }

    // Move
    transform = moveSelectionBy(opts, transform, direction, 0);

    // Select all cell.
    // We have to apply the transform so that "selectAllText"
    // can have access to an updated "startBlock"
    transform = transform.apply().transform();
    return selectAllText(transform).apply();
}

module.exports = onTab;
<|endoftext|>


<commit_before>'use strict';
var mocha = require('mocha');
var assert = require('power-assert');
var Vinyl = require('vinyl');
var mississippi = require('mississippi');
var GulpUglifyError = require('../lib/gulp-uglify-error');
var gulpUglify = require('../');

var pipe = mississippi.pipe;
var to = mississippi.to;
var from = mississippi.from;

var describe = mocha.describe;
var it = mocha.it;

describe('stream errors', function () {
  it('should report files in error', function (done) {
    var testFile = new Vinyl({
      cwd: '/home/terin/broken-promises/',
      base: '/home/terin/broken-promises/test',
      path: '/home/terin/broken-promises/test/test1.js',
      contents: new Buffer('function errorFunction(error)\n{')
    });

    pipe([
      from.obj([testFile]),
      gulpUglify(),
      to.obj(function (chunk, enc, next) {
        assert(false, 'we shouldn\t have gotten here');
        next();
      })
    ], function (err) {
      assert.ok(err instanceof Error, 'argument should be of type Error');
      assert.ok(err instanceof GulpUglifyError, 'argument should be of type GulpUglifyError');
      assert.equal(err.plugin, 'gulp-uglify', 'error is from gulp-uglify');
      assert.equal(err.fileName, testFile.path, 'error reports correct file name');
      assert.equal(err.cause.line, 2, 'error reports correct line number');
      assert.ok(err.stack, 'error has a stack');
      assert.ok(!err.showStack, 'error is configured to not print the stack');
      done();
    });
  });

  it('shouldn\'t blow up when given output options', function (done) {
    var testFile = new Vinyl({
      cwd: '/home/terin/broken-promises/',
      base: '/home/terin/broken-promises/test',
      path: '/home/terin/broken-promises/test/test2.js',
      contents: new Buffer('"use strict"; (function(console, first, second) { console.log(first + second) }(5, 10))')
    });

    pipe([
      from.obj([testFile]),
      gulpUglify({
        output: {
          exportAll: true
        }
      }),
      to.obj(function (chunk, enc, next) {
        assert(false, 'we shouldn\t have gotten here');
        next();
      })
    ], function (err) {
      assert.ok(err instanceof Error, 'argument should be of type Error');
      assert.ok(err instanceof GulpUglifyError, 'argument should be of type GulpUglifyError');
      assert.equal(err.cause.msg, '`exportAll` is not a supported option');
      assert.equal(err.plugin, 'gulp-uglify', 'error is from gulp-uglify');
      assert.equal(err.fileName, testFile.path, 'error reports correct file name');
      assert.ok(!err.showStack, 'error is configured to not print the stack');
      done();
    });
  });
});
<commit_msg>fix(tests): UglifyJS errors use "message" property<commit_after>'use strict';
var mocha = require('mocha');
var assert = require('power-assert');
var Vinyl = require('vinyl');
var mississippi = require('mississippi');
var GulpUglifyError = require('../lib/gulp-uglify-error');
var gulpUglify = require('../');

var pipe = mississippi.pipe;
var to = mississippi.to;
var from = mississippi.from;

var describe = mocha.describe;
var it = mocha.it;

describe('stream errors', function () {
  it('should report files in error', function (done) {
    var testFile = new Vinyl({
      cwd: '/home/terin/broken-promises/',
      base: '/home/terin/broken-promises/test',
      path: '/home/terin/broken-promises/test/test1.js',
      contents: new Buffer('function errorFunction(error)\n{')
    });

    pipe([
      from.obj([testFile]),
      gulpUglify(),
      to.obj(function (chunk, enc, next) {
        assert(false, 'we shouldn\t have gotten here');
        next();
      })
    ], function (err) {
      assert.ok(err instanceof Error, 'argument should be of type Error');
      assert.ok(err instanceof GulpUglifyError, 'argument should be of type GulpUglifyError');
      assert.equal(err.plugin, 'gulp-uglify', 'error is from gulp-uglify');
      assert.equal(err.fileName, testFile.path, 'error reports correct file name');
      assert.equal(err.cause.line, 2, 'error reports correct line number');
      assert.ok(err.stack, 'error has a stack');
      assert.ok(!err.showStack, 'error is configured to not print the stack');
      done();
    });
  });

  it('shouldn\'t blow up when given output options', function (done) {
    var testFile = new Vinyl({
      cwd: '/home/terin/broken-promises/',
      base: '/home/terin/broken-promises/test',
      path: '/home/terin/broken-promises/test/test2.js',
      contents: new Buffer('"use strict"; (function(console, first, second) { console.log(first + second) }(5, 10))')
    });

    pipe([
      from.obj([testFile]),
      gulpUglify({
        output: {
          exportAll: true
        }
      }),
      to.obj(function (chunk, enc, next) {
        assert(false, 'we shouldn\t have gotten here');
        next();
      })
    ], function (err) {
      assert.ok(err instanceof Error, 'argument should be of type Error');
      assert.ok(err instanceof GulpUglifyError, 'argument should be of type GulpUglifyError');
      assert.equal(err.cause.message, '`exportAll` is not a supported option');
      assert.equal(err.plugin, 'gulp-uglify', 'error is from gulp-uglify');
      assert.equal(err.fileName, testFile.path, 'error reports correct file name');
      assert.ok(!err.showStack, 'error is configured to not print the stack');
      done();
    });
  });
});
<|endoftext|>


<commit_before>var Path = require('path');

var gulp = require('gulp');
var gutil = require('gulp-util');
var del = require('del');
var rename = require('gulp-rename');
var jshint = require('gulp-jshint');
var stylish = require('jshint-stylish');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var qunit = require('gulp-qunit');
var preprocess = require('gulp-preprocess');

var fb = require('gulp-fb');

var paths = {
    src: [
        'src/__intro.js',

        // javascript extends
        'src/definition.js',
        'src/core.js',
        'src/math.js',
        'src/intersection.js',
        'src/callbacks-invoker.js',

        // basic classes
        'src/attribute.js',
        'src/class.js',
        'src/utils.js',
        'src/path.js',
        'src/object.js',
        'src/hash-object.js',
        'src/vec2.js',
        'src/matrix23.js',
        'src/rect.js',
        'src/polygon.js',
        'src/color.js',
        'src/deserialize.js',
        'src/instantiate.js',

        // assets
        'src/asset/asset.js',
        'src/asset/texture.js',
        'src/asset/sprite.js',
        'src/asset/atlas.js',
        'src/asset/font-info.js',
        'src/asset/json-asset.js',

        // editor utils
        'src/editor/utils.js',
        'src/editor/platform.js',
        'src/editor/serialize.js',
        'src/editor/serialize-nicify.js',
        'src/editor/dom.js',
        'src/editor/file-utils.js',

        'src/__outro.js',
    ],
    dev: 'bin/core.dev.js',
    min: 'bin/core.min.js',
    player_dev: 'bin/core.player.dev.js',
    player: 'bin/core.player.js',

    test: {
        src: 'test/unit/**/*.js',
        runner: 'test/lib/runner.html',
        lib_dev: [
            'bin/core.dev.js',
        ],
        lib_min: [
            'bin/core.min.js',
        ],
    },

    ref: {
        src: [
            'test/lib/*.js',
            'test/unit/_*.js',
        ],
        dest: '_references.js',
    },
};

// clean
gulp.task('clean', function() {
    del('bin/');
});

// js-hint
gulp.task('jshint', function() {
    return gulp.src(paths.src.concat( ['!**/__intro.js','!**/__outro.js'] ))
    .pipe(jshint({
        forin: false,
        multistr: true,
    }))
    .pipe(jshint.reporter(stylish))
    ;
});

// dev
gulp.task('dev', ['jshint', 'player-dev'], function() {
    return gulp.src(paths.src)
    .pipe(preprocess({context: { EDITOR: true, DEBUG: true, DEV: true }}))
    .pipe(concat('core.dev.js'))
    .pipe(gulp.dest('bin'))
    ;
});

// min
gulp.task('min', ['dev'], function() {
    return gulp.src(paths.src)
    .pipe(preprocess({context: { EDITOR: true, DEV: true }}))
    .pipe(concat('core.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest('bin'))
    ;
});

// player dev
gulp.task('player-dev', ['jshint'], function() {
    return gulp.src(paths.src.concat('!**/editor/**'))
    .pipe(preprocess({context: { PLAYER: true, DEBUG: true, DEV: true }}))
    .pipe(concat(Path.basename(paths.player_dev)))
    .pipe(gulp.dest(Path.dirname(paths.player_dev)))
    ;
});

// player
gulp.task('player', function() {
    return gulp.src(paths.src.concat('!**/editor/**'))
    .pipe(preprocess({context: { PLAYER: true }}))
    .pipe(concat(Path.basename(paths.player)))
    .pipe(gulp.dest(Path.dirname(paths.player)))
    ;
});

/////////////////////////////////////////////////////////////////////////////
// test
/////////////////////////////////////////////////////////////////////////////

gulp.task('unit-runner', function() {
    var js = paths.test.src;
    var dest = paths.test.src.split('*')[0];
    return gulp.src(js, { read: false, base: './' })
               .pipe(fb.toFileList())
               .pipe(fb.generateRunner(paths.test.runner,
                                         dest,
                                         'Fireball Core Test Suite',
                                         paths.test.lib_min,
                                         paths.test.lib_dev,
                                         paths.src))
               .pipe(gulp.dest(dest))
               ;
});

gulp.task('test', ['min', 'unit-runner'], function() {
    var timeOutInSeconds = 5;
    return gulp.src(['test/unit/**/*.html', '!**/*.dev.*'], { read: false })
               .pipe(qunit({ timeout: timeOutInSeconds }))
               ;
});

/////////////////////////////////////////////////////////////////////////////
// tasks
/////////////////////////////////////////////////////////////////////////////

// ref
gulp.task('ref', function() {
    var src = paths.src;//.concat(['!src/__intro.js', '!src/__outro.js']);
    var files = paths.ref.src.concat(src);
    var destPath = paths.ref.dest;
    return fb.generateReference(files, destPath);
});

// watch
gulp.task('watch-self', function() {
    gulp.watch(paths.src, ['dev', 'player-dev', 'player']).on( 'error', gutil.log );
});
gulp.task('watch', ['watch-self']);

//
gulp.task('all', ['min', 'test', 'ref', 'player-dev', 'player'] );
gulp.task('ci', ['min', 'test'] );
gulp.task('default', ['dev', 'min', 'player-dev', 'player'] );
<commit_msg>[GULP] merge task dev and min<commit_after>var Path = require('path');

var gulp = require('gulp');
var gutil = require('gulp-util');
var del = require('del');
var rename = require('gulp-rename');
var jshint = require('gulp-jshint');
var stylish = require('jshint-stylish');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var qunit = require('gulp-qunit');
var preprocess = require('gulp-preprocess');

var fb = require('gulp-fb');

var paths = {
    src: [
        'src/__intro.js',

        // javascript extends
        'src/definition.js',
        'src/core.js',
        'src/math.js',
        'src/intersection.js',
        'src/callbacks-invoker.js',

        // basic classes
        'src/attribute.js',
        'src/class.js',
        'src/utils.js',
        'src/path.js',
        'src/object.js',
        'src/hash-object.js',
        'src/vec2.js',
        'src/matrix23.js',
        'src/rect.js',
        'src/polygon.js',
        'src/color.js',
        'src/deserialize.js',
        'src/instantiate.js',

        // assets
        'src/asset/asset.js',
        'src/asset/texture.js',
        'src/asset/sprite.js',
        'src/asset/atlas.js',
        'src/asset/font-info.js',
        'src/asset/json-asset.js',

        // editor utils
        'src/editor/utils.js',
        'src/editor/platform.js',
        'src/editor/serialize.js',
        'src/editor/serialize-nicify.js',
        'src/editor/dom.js',
        'src/editor/file-utils.js',

        'src/__outro.js',
    ],
    dev: 'bin/core.dev.js',
    min: 'bin/core.min.js',
    player_dev: 'bin/core.player.dev.js',
    player: 'bin/core.player.js',

    test: {
        src: 'test/unit/**/*.js',
        runner: 'test/lib/runner.html',
        lib_dev: [
            'bin/core.dev.js',
        ],
        lib_min: [
            'bin/core.min.js',
        ],
    },

    ref: {
        src: [
            'test/lib/*.js',
            'test/unit/_*.js',
        ],
        dest: '_references.js',
    },
};

// clean
gulp.task('clean', function() {
    del('bin/');
});

// js-hint
gulp.task('jshint', function() {
    return gulp.src(paths.src.concat( ['!**/__intro.js','!**/__outro.js'] ))
    .pipe(jshint({
        forin: false,
        multistr: true,
    }))
    .pipe(jshint.reporter(stylish))
    ;
});

// js dev
gulp.task('js-dev', function() {
    return gulp.src(paths.src)
    .pipe(preprocess({context: { EDITOR: true, DEBUG: true, DEV: true }}))
    .pipe(concat('core.dev.js'))
    .pipe(gulp.dest('bin'))
    ;
});

// js min
gulp.task('js-min', function() {
    return gulp.src(paths.src)
    .pipe(preprocess({context: { EDITOR: true, DEV: true }}))
    .pipe(concat('core.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest('bin'))
    ;
});

// player dev
gulp.task('js-player-dev', function() {
    return gulp.src(paths.src.concat('!**/editor/**'))
    .pipe(preprocess({context: { PLAYER: true, DEBUG: true, DEV: true }}))
    .pipe(concat(Path.basename(paths.player_dev)))
    .pipe(gulp.dest(Path.dirname(paths.player_dev)))
    ;
});

// player
gulp.task('js-player', function() {
    return gulp.src(paths.src.concat('!**/editor/**'))
    .pipe(preprocess({context: { PLAYER: true }}))
    .pipe(concat(Path.basename(paths.player)))
    .pipe(gulp.dest(Path.dirname(paths.player)))
    ;
});

gulp.task('js-all', ['jshint', 'js-dev', 'js-min', 'js-player-dev', 'js-player']);

/////////////////////////////////////////////////////////////////////////////
// test
/////////////////////////////////////////////////////////////////////////////

gulp.task('unit-runner', function() {
    var js = paths.test.src;
    var dest = paths.test.src.split('*')[0];
    return gulp.src(js, { read: false, base: './' })
               .pipe(fb.toFileList())
               .pipe(fb.generateRunner(paths.test.runner,
                                         dest,
                                         'Fireball Core Test Suite',
                                         paths.test.lib_min,
                                         paths.test.lib_dev,
                                         paths.src))
               .pipe(gulp.dest(dest))
               ;
});

gulp.task('test', ['js-min', 'unit-runner'], function() {
    var timeOutInSeconds = 5;
    return gulp.src(['test/unit/**/*.html', '!**/*.dev.*'], { read: false })
               .pipe(qunit({ timeout: timeOutInSeconds }))
               ;
});

/////////////////////////////////////////////////////////////////////////////
// tasks
/////////////////////////////////////////////////////////////////////////////

// ref
gulp.task('ref', function() {
    var src = paths.src;//.concat(['!src/__intro.js', '!src/__outro.js']);
    var files = paths.ref.src.concat(src);
    var destPath = paths.ref.dest;
    return fb.generateReference(files, destPath);
});

gulp.task('default', ['js-all'] );
gulp.task('dev', ['default']);
gulp.task('all', ['default', 'test', 'ref'] );
gulp.task('ci', ['jshint', 'test'] );

// watch
gulp.task('watch-self', function() {
    gulp.watch(paths.src, ['dev']).on( 'error', gutil.log );
});
gulp.task('watch', ['watch-self']);
<|endoftext|>


<commit_before>var BigNumber = require('bignumber.js'),
    util = require('util'),
    abs = Math.abs;

/**
 * Model object representing an Order.
 *
 * Similar to types defined here: https://bitme.github.io/#js-orders
 *
 * @param {string|null} id  Global unique identifier for this order, usually
 *     provided by the exchange inwhich the order lives. If {@code null} then it
 *     should be filled in later.
 * @param {string} type One of 'BID' or 'ASK'.
 * @param {string|BigNumber} quantity Quantity of order (e.g. number of BTC).
 * @param {string|BigNumber} rate Price per unit (e.g. number of USD).
 * @param {string=} state Indicate if the order is in a transition state, such as
 *     in the process of being fulfilled.
 * @param {string=} exchange Where this order currently lives, if anywhere.
 */

var Order = module.exports.Order = function(id, type, quantity, rate, state, exchange) {
    if (id === undefined) {
        throw new Error('Order id must be defined.');
    }
    if (type !== 'BID' && type !== 'ASK') {
        throw new Error('Order type must be one of "BID" or "ASK", not "'+ type +'"');
    }
    if (quantity===undefined || rate===undefined) {
        throw new Error('Order must have a defined quantity and rate.');
    };

    this.id = id;
    this.type = type;
    this.quantity = BigNumber(quantity);
    this.rate = BigNumber(rate);
    this.state = state;
    this.exchange = exchange;
};

Order.prototype.toObject = function() {
    return {
        'id': this.id,
        'type': this.type,
        'quantity': this.quantity.toFixed(),
        'rate': this.rate.toFixed(),
        'state': this.state,
        'exchange': this.exchange
    }
};

Order.prototype.toString = function() {
    return util.format('[Order #%s: %s %s @ $%s]', this.id, this.type, this.quantity.toFixed(), this.rate.toFixed());
};

/**
 * Return a copy of the Order object but with with some properties overridden.
 *
 * The id, state, and exchange will not be copied.
 *
 * @param {object} override Object containing properties to override in the clone.
 * @param {number=} premium Price multiplier to apply on rate, inverted by type.
 * @param {boolean=} invertType If true, the type will be inverted pre-override.
 * @return {Order} A new Order object.
 */
Order.prototype.clone = function(override, premium, invertType) {
    var o = {
        'id': null,
        'type': this.type,
        'quantity': this.quantity,
        'rate': this.rate
    };

    if (invertType===true) {
        o.type = o.type == 'BID' ? 'ASK' : 'BID';
    }

    for (var key in override) {
        o[key] = override[key];
    }

    var newOrder = new Order(o.id, o.type, o.quantity, o.rate, o.state, o.exchange);
    newOrder.rate = newOrder.getPremiumRate(premium);
    return newOrder;
};

/**
 * @param {number=} premium Price multiplier to apply on rate, inverted by type.
 * @return {BigNumber} Rate with premium applied.
 */
Order.prototype.getPremiumRate = function(premium) {
    if (premium==undefined) {
        return this.rate;
    }
    if (this.type == 'ASK') {
        return this.rate.times(premium);
    }
    if (this.type == 'BID') {
        return this.rate.dividedBy(premium);
    }
};

/**
 * Given a list of old and new orders, return any quantity changes as a list of
 * {@code Order} objects.
 *
 * Will not check for new newOrders, only missing oldOrders.
 *
 * @param {Array.<Order>} oldOrders
 * @param {Array.<Order>} newOrders
 * @return {Array.<Order>}
 */
var diffOrders = module.exports.diffOrders = function(oldOrders, newOrders) {
    var newOrderIdx = {};
    newOrders.forEach(function(order) {
        newOrderIdx[order.id] = order;
    });

    var changed = [];

    oldOrders.forEach(function(order) {
        var newOrder = newOrderIdx[order.id];
        if (newOrder === undefined) {
            // Missing.
            changed.push(order);
            return;
        }

        if (!order.quantity.eq(newOrder.quantity)) {
            // Changed.
            changed.push(newOrder.clone({
                'quantity': order.quantity.minus(newOrder.quantity)
            }));
            return;
        }
    });

    return changed;
};

/**
* Combine sorted orders (by spread from the mean price) into a subset of total
* value being at least minValue (including premium). Discard any remaining
* orders.
*
* @param {Array.<Order>} orders Orders to aggregate.
* @param {number=} minValue Minimum {@code rate*quantity} value of returned orders.
* @param {number=} premium Premium to apply to aggregated orders.
* @param {number=} maxOrers Maximum number of orders to return.
* @return {Array.<Order>} Sorted aggregated orders representing a subset of input orders with premium applied.
*/
var aggregateOrders = module.exports.aggregateOrders = function(orders, minValue, premium, maxOrders) {
    var aggregated = {
        'ASK': {
            value: BigNumber(0),
            quantity: BigNumber(0)
        },
        'BID': {
            value: BigNumber(0),
            quantity: BigNumber(0)
        }
    };
    var r = [];

    orders.every(function(order, i) {
        if (i > maxOrders) {
            return false;
        }
        var rate = order.getPremiumRate(premium);
        var agg = aggregated[order.type];

        agg.value = agg.value.plus(rate.times(order.quantity));
        agg.quantity = agg.quantity.plus(order.quantity);

        if (agg.value < minValue) {
            // Keep accumulating.
            return true;
        }

        r.push(new Order(null, order.type, agg.quantity, agg.value.dividedBy(agg.quantity)));
        agg.value = BigNumber(0);
        agg.quantity = BigNumber(0);
        return true;
    });

    return r;
};

/**
 * Given a list of placed orders and a list of desired orders, return
 * instructions for modifying the placed orders such that it matches the
 * desires orders, without regard to the order id.
 *
 * Will re-order the given parameters.
 *
 * @param {Array.<Order>} placedOrders Currently placed orders.
 * @param {Array.<Order>} newOrders New desired state of placedOrders.
 * @return {{cancel: Array.<Order>, place: Array.<Order>}}
 */
var patchOrders = module.exports.patchOrders = function(placedOrders, newOrders) {
    // TODO: Add tolerance value to skip replacing orders that only changed slightly?
    // TODO: This is not the most efficient implementation, could do a better job if it matters.
    sortOrders(placedOrders);
    sortOrders(newOrders);

    var patch = {
        'cancel': [],
        'place': []
    };

    var p = 0, n = 0;
    while (true) {
        if (p >= placedOrders.length) {
            // The rest must be new.
            patch.place = patch.place.concat(newOrders.slice(n));
            break;
        } else if (n >= newOrders.length) {
            // The rest must be old.
            patch.cancel = patch.cancel.concat(placedOrders.slice(p));
            break;
        }

        var placedOrder = placedOrders[p], newOrder = newOrders[n];
        if (placedOrder.type === newOrder.type && placedOrder.rate.eq(newOrder.rate) && placedOrder.quantity.eq(newOrder.quantity)) {
            // Same order, skip.
            p++;
            n++;
            continue;
        }

        if (placedOrder.rate < newOrder.rate) {
            p++;
            patch.cancel.push(placedOrder);
            continue
        } else {
            n++;
            patch.place.push(newOrder);
            continue;
        }

    }

    return {
        'cancel': placedOrders,
        'place': newOrders
    }
};

/**
 * Sort orders by (spread from mean, quantity, type, rate).
 *
 * If meanRate is not given, then it's treated as 0, so orders will be sorted
 * by rate ascending.
 */
var sortOrders = module.exports.sortOrders = function(orders, meanRate) {
    if (meanRate === undefined) meanRate = 0;
    return orders.sort(function(a, b) {
        var cmp = abs(meanRate-a.rate) - abs(meanRate-b.rate);
        if (cmp == 0) cmp = a.quantity.comparedTo(b.quantity);
        if (cmp == 0 && a.type !== b.type) cmp = a.type === 'ASK' ? 1 : -1;
        if (cmp == 0) cmp = a.rate.comparedTo(b.rate);
        return cmp;
    });
};

/**
 * Given a list of orders, return the combined value of all the asks and bids.
 *
 * Rounded to a Number, not precise.
 *
 * @param {Array.<Order>}
 * @return {{asks: number, bids: number}}
 */
var totalValue = module.exports.totalValue = function(orders) {
    var r = {
        'ASK': BigNumber(0),
        'BID': BigNumber(0)
    };
    orders.forEach(function(o) {
        r[o.type] = r[o.type].plus(o.quantity.times(o.rate));
    });
    return {
        'asks': r['ASK'].toNumber(),
        'bids': r['BID'].toNumber()
    };
};

/**
 * Given a list of orders, return the spread calculations.
 *
 * @param {Array.<Order>} orders
 * return {object}
 */
var getSpread = module.exports.getSpread = function(orders) {
    var rates = {'ASK': [], 'BID': []};

    var totalQuantity = BigNumber(0);
    var totalValue = BigNumber(0);
    orders.forEach(function(o) {
        totalQuantity = totalQuantity.plus(o.quantity);
        totalValue = totalValue.plus(o.quantity.times(o.rate));
        rates[o.type].push(o.rate);
    });

    var bid = Math.max.apply(null, rates['BID']);
    var ask = Math.min.apply(null, rates['ASK']);
    var amount, percent, mean;

    if (bid === -Infinity) {
        bid = null;
        mean = ask;
    } else if (ask === Infinity) {
        ask = null;
        mean = bid;
    } else {
        amount = ask - bid;
        percent = (amount / ask) * 100.0;
        mean = (bid + ask) / 2.0;
    }

    if (ask === bid === null) {
        mean = undefined;
    }

    return {
        bid: bid,
        ask: ask,
        numBids: rates['BID'].length,
        numAsks: rates['ASK'].length,
        amount: amount,
        percent: percent,
        mean: mean,
        totalQuantity: totalQuantity.toNumber(),
        totalValue: totalValue.toNumber()
    }
};
<commit_msg>Order.prototype.comparedTo<commit_after>var BigNumber = require('bignumber.js'),
    util = require('util'),
    abs = Math.abs;

/**
 * Model object representing an Order.
 *
 * Similar to types defined here: https://bitme.github.io/#js-orders
 *
 * @param {string|null} id  Global unique identifier for this order, usually
 *     provided by the exchange inwhich the order lives. If {@code null} then it
 *     should be filled in later.
 * @param {string} type One of 'BID' or 'ASK'.
 * @param {string|BigNumber} quantity Quantity of order (e.g. number of BTC).
 * @param {string|BigNumber} rate Price per unit (e.g. number of USD).
 * @param {string=} state Indicate if the order is in a transition state, such as
 *     in the process of being fulfilled.
 * @param {string=} exchange Where this order currently lives, if anywhere.
 */

var Order = module.exports.Order = function(id, type, quantity, rate, state, exchange) {
    if (id === undefined) {
        throw new Error('Order id must be defined.');
    }
    if (type !== 'BID' && type !== 'ASK') {
        throw new Error('Order type must be one of "BID" or "ASK", not "'+ type +'"');
    }
    if (quantity===undefined || rate===undefined) {
        throw new Error('Order must have a defined quantity and rate.');
    };

    this.id = id;
    this.type = type;
    this.quantity = BigNumber(quantity);
    this.rate = BigNumber(rate);
    this.state = state;
    this.exchange = exchange;
};

Order.prototype.toObject = function() {
    return {
        'id': this.id,
        'type': this.type,
        'quantity': this.quantity.toFixed(),
        'rate': this.rate.toFixed(),
        'state': this.state,
        'exchange': this.exchange
    }
};

Order.prototype.toString = function() {
    return util.format('[Order #%s: %s %s @ $%s]', this.id, this.type, this.quantity.toFixed(), this.rate.toFixed());
};

Order.prototype.comparedTo = function(other) {
    var cmp = this.rate.comparedTo(other.rate);
    if (cmp == 0) cmp = this.quantity.comparedTo(other.quantity);
    if (cmp == 0 && this.type !== other.type) cmp = this.type === 'ASK' ? 1 : -1;
    return cmp;
};

/**
 * Return a copy of the Order object but with with some properties overridden.
 *
 * The id, state, and exchange will not be copied.
 *
 * @param {object} override Object containing properties to override in the clone.
 * @param {number=} premium Price multiplier to apply on rate, inverted by type.
 * @param {boolean=} invertType If true, the type will be inverted pre-override.
 * @return {Order} A new Order object.
 */
Order.prototype.clone = function(override, premium, invertType) {
    var o = {
        'id': null,
        'type': this.type,
        'quantity': this.quantity,
        'rate': this.rate
    };

    if (invertType===true) {
        o.type = o.type == 'BID' ? 'ASK' : 'BID';
    }

    for (var key in override) {
        o[key] = override[key];
    }

    var newOrder = new Order(o.id, o.type, o.quantity, o.rate, o.state, o.exchange);
    newOrder.rate = newOrder.getPremiumRate(premium);
    return newOrder;
};

/**
 * @param {number=} premium Price multiplier to apply on rate, inverted by type.
 * @return {BigNumber} Rate with premium applied.
 */
Order.prototype.getPremiumRate = function(premium) {
    if (premium==undefined) {
        return this.rate;
    }
    if (this.type == 'ASK') {
        return this.rate.times(premium);
    }
    if (this.type == 'BID') {
        return this.rate.dividedBy(premium);
    }
};

/**
 * Given a list of old and new orders, return any quantity changes as a list of
 * {@code Order} objects.
 *
 * Will not check for new newOrders, only missing oldOrders.
 *
 * @param {Array.<Order>} oldOrders
 * @param {Array.<Order>} newOrders
 * @return {Array.<Order>}
 */
var diffOrders = module.exports.diffOrders = function(oldOrders, newOrders) {
    var newOrderIdx = {};
    newOrders.forEach(function(order) {
        newOrderIdx[order.id] = order;
    });

    var changed = [];

    oldOrders.forEach(function(order) {
        var newOrder = newOrderIdx[order.id];
        if (newOrder === undefined) {
            // Missing.
            changed.push(order);
            return;
        }

        if (!order.quantity.eq(newOrder.quantity)) {
            // Changed.
            changed.push(newOrder.clone({
                'quantity': order.quantity.minus(newOrder.quantity)
            }));
            return;
        }
    });

    return changed;
};

/**
* Combine sorted orders (by spread from the mean price) into a subset of total
* value being at least minValue (including premium). Discard any remaining
* orders.
*
* @param {Array.<Order>} orders Orders to aggregate.
* @param {number=} minValue Minimum {@code rate*quantity} value of returned orders.
* @param {number=} premium Premium to apply to aggregated orders.
* @param {number=} maxOrers Maximum number of orders to return.
* @return {Array.<Order>} Sorted aggregated orders representing a subset of input orders with premium applied.
*/
var aggregateOrders = module.exports.aggregateOrders = function(orders, minValue, premium, maxOrders) {
    var aggregated = {
        'ASK': {
            value: BigNumber(0),
            quantity: BigNumber(0)
        },
        'BID': {
            value: BigNumber(0),
            quantity: BigNumber(0)
        }
    };
    var r = [];

    orders.every(function(order, i) {
        if (i > maxOrders) {
            return false;
        }
        var rate = order.getPremiumRate(premium);
        var agg = aggregated[order.type];

        agg.value = agg.value.plus(rate.times(order.quantity));
        agg.quantity = agg.quantity.plus(order.quantity);

        if (agg.value < minValue) {
            // Keep accumulating.
            return true;
        }

        r.push(new Order(null, order.type, agg.quantity, agg.value.dividedBy(agg.quantity)));
        agg.value = BigNumber(0);
        agg.quantity = BigNumber(0);
        return true;
    });

    return r;
};

/**
 * Given a list of placed orders and a list of desired orders, return
 * instructions for modifying the placed orders such that it matches the
 * desires orders, without regard to the order id.
 *
 * Will re-order the given parameters.
 *
 * @param {Array.<Order>} placedOrders Currently placed orders.
 * @param {Array.<Order>} newOrders New desired state of placedOrders.
 * @return {{cancel: Array.<Order>, place: Array.<Order>}}
 */
var patchOrders = module.exports.patchOrders = function(placedOrders, newOrders) {
    // TODO: Add tolerance value to skip replacing orders that only changed slightly?
    // TODO: This is not the most efficient implementation, could do a better job if it matters.
    sortOrders(placedOrders);
    sortOrders(newOrders);

    var patch = {
        'cancel': [],
        'place': []
    };

    var p = 0, n = 0;
    while (true) {
        if (p >= placedOrders.length) {
            // The rest must be new.
            patch.place = patch.place.concat(newOrders.slice(n));
            break;
        } else if (n >= newOrders.length) {
            // The rest must be old.
            patch.cancel = patch.cancel.concat(placedOrders.slice(p));
            break;
        }

        var placedOrder = placedOrders[p], newOrder = newOrders[n];
        if (placedOrder.type === newOrder.type && placedOrder.rate.eq(newOrder.rate) && placedOrder.quantity.eq(newOrder.quantity)) {
            // Same order, skip.
            p++;
            n++;
            continue;
        }

        if (placedOrder.rate < newOrder.rate) {
            p++;
            patch.cancel.push(placedOrder);
            continue
        } else {
            n++;
            patch.place.push(newOrder);
            continue;
        }

    }

    return {
        'cancel': placedOrders,
        'place': newOrders
    }
};

/**
 * Sort orders by (spread from mean, rate, quantity, type).
 *
 * If meanRate is not given, then it's treated as 0, so orders will be sorted
 * by rate ascending.
 */
var sortOrders = module.exports.sortOrders = function(orders, meanRate) {
    if (meanRate === undefined) meanRate = 0;
    return orders.sort(function(a, b) {
        var cmp = abs(meanRate-a.rate) - abs(meanRate-b.rate);
        if (cmp == 0) cmp = a.comparedTo(b);
        return cmp;
    });
};

/**
 * Given a list of orders, return the combined value of all the asks and bids.
 *
 * Rounded to a Number, not precise.
 *
 * @param {Array.<Order>}
 * @return {{asks: number, bids: number}}
 */
var totalValue = module.exports.totalValue = function(orders) {
    var r = {
        'ASK': BigNumber(0),
        'BID': BigNumber(0)
    };
    orders.forEach(function(o) {
        r[o.type] = r[o.type].plus(o.quantity.times(o.rate));
    });
    return {
        'asks': r['ASK'].toNumber(),
        'bids': r['BID'].toNumber()
    };
};

/**
 * Given a list of orders, return the spread calculations.
 *
 * @param {Array.<Order>} orders
 * return {object}
 */
var getSpread = module.exports.getSpread = function(orders) {
    var rates = {'ASK': [], 'BID': []};

    var totalQuantity = BigNumber(0);
    var totalValue = BigNumber(0);
    orders.forEach(function(o) {
        totalQuantity = totalQuantity.plus(o.quantity);
        totalValue = totalValue.plus(o.quantity.times(o.rate));
        rates[o.type].push(o.rate);
    });

    var bid = Math.max.apply(null, rates['BID']);
    var ask = Math.min.apply(null, rates['ASK']);
    var amount, percent, mean;

    if (bid === -Infinity) {
        bid = null;
        mean = ask;
    } else if (ask === Infinity) {
        ask = null;
        mean = bid;
    } else {
        amount = ask - bid;
        percent = (amount / ask) * 100.0;
        mean = (bid + ask) / 2.0;
    }

    if (ask === bid === null) {
        mean = undefined;
    }

    return {
        bid: bid,
        ask: ask,
        numBids: rates['BID'].length,
        numAsks: rates['ASK'].length,
        amount: amount,
        percent: percent,
        mean: mean,
        totalQuantity: totalQuantity.toNumber(),
        totalValue: totalValue.toNumber()
    }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var util = require('util');
var _ = require('underscore');

function MyFunctionalShape() {
  if(! this instanceof MyFunctionalShape) {
    return new MyFunctionalShape();
  }
  var self = this;
  console.log('parent ctor: this=' + this);
}

MyFunctionalShape.prototype.baseMethod = function() { }

function MyFunctionalCircle() {
  if(!_.isObject(this) || !(this instanceof MyFunctionalCircle)) {
    return new MyFunctionalCircle(arguments);
  }
  var self = this;
  MyFunctionalShape.apply(self);

  self.fn = function() { }
  console.log('child ctor: this=' + this);
}

MyFunctionalCircle.super_ = MyFunctionalShape;
MyFunctionalCircle.prototype = Object.create(MyFunctionalShape.prototype, {
  constructor: {
    value: MyFunctionalCircle,
    enumerable: false,
    writable: true,
    configurable: true
  }
});

MyFunctionalCircle.prototype.method = function() {
console.log("a: " + util.inspect(this, true, 99));

};

MyFunctionalShape.prototype.baseMethod2 = function() {};

function lookAt(obj, name) {
  console.log("Looking at " + name + ":");
  for(key in obj) {
    console.log(name + "['" + key + "'] = " + obj[key]);
  }
}

var a = new MyFunctionalCircle();
lookAt(a, 'a');
console.log("a: " + util.inspect(a, true, 99));
a.method();
<commit_msg>delete unintentionally committed file<commit_after><|endoftext|>


<commit_before>// @ts-check
const gulp = require('gulp');
const bump = require('gulp-bump');
const conventionalChangelog = require('gulp-conventional-changelog');
const fs = require('fs');
const path = require('path');
const exec = require('child_process').exec;
const promisify = require('util').promisify;
const args = require('./build/args');
const DIR_DOC = './doc';
const FILE_DOC = path.resolve(DIR_DOC, 'CHANGELOG.md');

gulp.task('build', async () => {
  const { stderr: err1, stdout: out1 } = await promisify(exec)('npm run build');
  if (err1) {
    console.log('==== build warning ====');
    console.log(err1);
  }
  console.log('==== build output ====');
  console.log(out1);
});

gulp.task('lint', async () => {
  const { stderr: err2, stdout: out2 } = await promisify(exec)('npm run lint');
  if (err2) {
    console.log('==== lint warning ====');
    console.log(err2);
  }
  console.log('==== lint output ====');
  console.log(out2);
});

gulp.task('doc', async () => {
  const { stderr, stdout } = await promisify(exec)('npm run doc');
  if (stderr) {
    console.log('==== doc warning ====');
    console.log(stderr);
  }
  // quite a pain (no API from typeodc) to generate a json string
  // in memory, so just double write
  try {
    const content = fs.readFileSync(DIR_DOC + '/api.json', { encoding: 'utf-8' });
    fs.writeFileSync(path.resolve(DIR_DOC, 'api.json'), JSON.stringify(JSON.parse(content)));
  } finally {}
  console.log('==== doc output ====');
  console.log(stdout);
});

gulp.task('changelog', function () {
  return gulp
    .src(FILE_DOC)
    .pipe(conventionalChangelog({

    }))
    .pipe(gulp.dest(DIR_DOC));
});

gulp.task('bump-version', function () {
  return gulp.src(['./package.json', './bower.json'])
    .pipe(bump({ type: args.bump })) //major|minor|patch|prerelease
    .pipe(gulp.dest('./'));
});

gulp.task(
  'prepare-release',
  gulp.series(
    'build',
    'lint',
    gulp.parallel(
      'doc',
      'bump-version',
      'changelog'
    )
  )
);
<commit_msg>chore(build): inline args file<commit_after>// @ts-check
const gulp = require('gulp');
const bump = require('gulp-bump');
const conventionalChangelog = require('gulp-conventional-changelog');
const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const exec = require('child_process').exec;
const promisify = require('util').promisify;
const DIR_DOC = './doc';
const FILE_DOC = path.resolve(DIR_DOC, 'CHANGELOG.md');
/**@type {{ bump: 'major' | 'minor' | 'patch' | 'prerelease' }}
 // @ts-ignore */
const argv = yargs.argv;
const validBumpTypes = "major|minor|patch|prerelease".split("|");
/**@type  */
const bumpType = (argv.bump || 'patch').toLowerCase();

if(validBumpTypes.indexOf(bumpType) === -1) {
  throw new Error('Unrecognized bump "' + bumpType + '".');
}

gulp.task('build', async () => {
  const { stderr: err1, stdout: out1 } = await promisify(exec)('npm run build');
  if (err1) {
    console.log('==== build warning ====');
    console.log(err1);
  }
  console.log('==== build output ====');
  console.log(out1);
});

gulp.task('lint', async () => {
  const { stderr: err2, stdout: out2 } = await promisify(exec)('npm run lint');
  if (err2) {
    console.log('==== lint warning ====');
    console.log(err2);
  }
  console.log('==== lint output ====');
  console.log(out2);
});

gulp.task('doc', async () => {
  const { stderr, stdout } = await promisify(exec)('npm run doc');
  if (stderr) {
    console.log('==== doc warning ====');
    console.log(stderr);
  }
  // quite a pain (no API from typeodc) to generate a json string
  // in memory, so just double write
  try {
    const content = fs.readFileSync(DIR_DOC + '/api.json', { encoding: 'utf-8' });
    fs.writeFileSync(path.resolve(DIR_DOC, 'api.json'), JSON.stringify(JSON.parse(content)));
  } finally {}
  console.log('==== doc output ====');
  console.log(stdout);
});

gulp.task('changelog', function () {
  return gulp
    .src(FILE_DOC)
    .pipe(conventionalChangelog({}))
    .pipe(gulp.dest(DIR_DOC));
});

gulp.task('bump-version', function () {
  return gulp.src(['./package.json', './bower.json'])
    .pipe(bump({ type: bumpType }))
    .pipe(gulp.dest('./'));
});

gulp.task(
  'prepare-release',
  gulp.series(
    'build',
    'lint',
    gulp.parallel(
      'doc',
      'bump-version',
      'changelog'
    )
  )
);
<|endoftext|>


<commit_before>const React = require("react");

exports.Footer = class Footer extends React.Component {
  render() {
    return (

              Terms
              Privacy Notice
              Report IP Infringement
              <a href={ `mailto:pageshot-feedback@mozilla.com?subject=Page%20Shot%20Feedback&body=Feedback%20regarding:%20${this.props.forUrl}` } target="_blank">Send Feedback
              GitHub
              {this.props.authenticated ? Remove All Data : null}

    );
  }
};
<commit_msg>Fix #1604, direct feedback to Discourse<commit_after>const React = require("react");

exports.Footer = class Footer extends React.Component {
  render() {
    return (

              Terms
              Privacy Notice
              Report IP Infringement
              Give Feedback
              GitHub
              {this.props.authenticated ? Remove All Data : null}

    );
  }
};
<|endoftext|>