<commit_before>var url = require("url");
var home = require('./endpoints/home');
var ping = require('./endpoints/ping');

exports.onRequest = function (request, response) {
    var routes = [
      { resource:/^\/$/,            endpoint:home.handle },
      { resource:/^\/ping$/,        endpoint:ping.handle },
      { resource:/^\/minesweeper$/, endpoint: function() { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(); }},
      { resource:/^.*$/,            endpoint:answerWith404 },
    ];
  var parsedUrl = url.parse(request.url);

  routes.forEach(function(route) {
    if(route.resource.test(parsedUrl.pathname)) {
      route.endpoint(request, response);
    }
  });
};

function answerWith404(request, response) {
  response.writeHead(404, {'Content-Type': 'text/plain'});
  response.end("page not found.");
}
<commit_msg>extracted minesweeper in its own endpoint<commit_after>var url = require("url");
var home = require('./endpoints/home');
var minesweeper = require('./endpoints/minesweeper');
var ping = require('./endpoints/ping');

exports.onRequest = function (request, response) {
    var routes = [
      { resource:/^\/$/,            endpoint:home.handle },
      { resource:/^\/minesweeper$/, endpoint:minesweeper.handle},
      { resource:/^\/ping$/,        endpoint:ping.handle },
      { resource:/^.*$/,            endpoint:answerWith404 },
    ];
  var parsedUrl = url.parse(request.url);

  routes.forEach(function(route) {
    if(route.resource.test(parsedUrl.pathname)) {
      route.endpoint(request, response);
    }
  });
};

function answerWith404(request, response) {
  response.writeHead(404, {'Content-Type': 'text/plain'});
  response.end("page not found.");
}
<|endoftext|>


<commit_before>/*
 * jQuery UI Spinner @VERSION
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Spinner
 *
 * Depends:
 *  jquery.ui.core.js
 *  jquery.ui.widget.js
 */
(function($) {

// shortcut constants
var pageModifier = 10;

$.widget('ui.spinner', {
	options: {
		incremental: true,
		max: Number.MAX_VALUE,
		min: -Number.MAX_VALUE,
		numberformat: null,
		step: 1,
		value: null
	},

	_create: function() {
		// html5 attributes initalization
		// TODO refactor
		var min = this.element.attr("min");
		if (typeof min == "string" && min.length > 0) {
			this.options.min = this._parse(min);
		}
		var max = this.element.attr("max");
		if (typeof max == "string" && max.length > 0) {
			this.options.max = this._parse(max);
		}
		var step = this.element.attr("step");
		if (typeof step == "string" && step.length > 0) {
			this.options.step = this._parse(step);
		}
		this.value(this.options.value !== null ? this.options.value : this.element.val() || 0);
		this._draw();
		this._mousewheel();
		this._aria();
	},

	_draw: function() {
		var self = this,
			options = self.options;

		var uiSpinner = this.uiSpinner = self.element
			.addClass('ui-spinner-input')
			.attr('autocomplete', 'off')
			.wrap(self._uiSpinnerHtml())
			.parent()
				// add buttons
				.append(self._buttonHtml())
				// add behaviours
				.hover(function() {
					if (!options.disabled) {
						$(this).addClass('ui-state-hover');
					}
					self.hovered = true;
				}, function() {
					$(this).removeClass('ui-state-hover');
					self.hovered = false;
				});

		// TODO: need a better way to exclude IE8 without resorting to $.browser.version
		// fix inline-block issues for IE. Since IE8 supports inline-block we need to exclude it.
		if (!$.support.opacity && uiSpinner.css('display') == 'inline-block' && $.browser.version < 8) {
			uiSpinner.css('display', 'inline');
		}

		this.element
			.bind('keydown.spinner', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self._start(event)) {
					return self._keydown(event);
				}
				return true;
			})
			.bind('keyup.spinner', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			})
			.bind('focus.spinner', function() {
				uiSpinner.addClass('ui-state-active');
				self.focused = true;
			})
			.bind('blur.spinner', function(event) {
				self.value(self.element.val());
				if (!self.hovered) {
					uiSpinner.removeClass('ui-state-active');
				}
				self.focused = false;
			});

		// button bindings
		this.buttons = uiSpinner.find('.ui-spinner-button')
			.attr("tabIndex", -1)
			.button()
			.first()
				.removeClass("ui-corner-all")
			.end()
			.last()
				.removeClass("ui-corner-all")
			.end()
			.bind('mousedown', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self._start(event) === false) {
					return false;
				}
				self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);
			})
			.bind('mouseup', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self.counter == 1) {
					self._spin(($(this).hasClass('ui-spinner-up') ? 1 : -1) * self.options.step, event);
				}
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			})
			.bind("mouseenter", function() {
				if (self.options.disabled) {
					return;
				}
				// button will add ui-state-active if mouse was down while mouseleave and kept down
				if ($(this).hasClass("ui-state-active")) {
					if (self._start(event) === false) {
						return false;
					}
					self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);
				}
			})
			.bind("mouseleave", function() {
				if (self.timer && self.spinning) {
					self._stop(event);
					self._change(event);
				}
			});

		// disable spinner if element was already disabled
		if (options.disabled) {
			this.disable();
		}
	},

	_keydown: function(event) {
		var o = this.options,
			KEYS = $.ui.keyCode;

		switch (event.keyCode) {
		case KEYS.UP:
			this._repeat(null, 1, event);
			return false;
		case KEYS.DOWN:
			this._repeat(null, -1, event);
			return false;
		case KEYS.PAGE_UP:
			this._repeat(null, pageModifier, event);
			return false;
		case KEYS.PAGE_DOWN:
			this._repeat(null, -pageModifier, event);
			return false;

		case KEYS.ENTER:
			this.value(this.element.val());
		}

		return true;
	},

	_mousewheel: function() {
		var self = this;
		this.element.bind("mousewheel.spinner", function(event, delta) {
			if (self.options.disabled) {
				return;
			}
			if (!self._start(event)) {
				return false;
			}
			self._spin((delta > 0 ? 1 : -1) * self.options.step, event);
			if (self.timeout) {
				window.clearTimeout(self.timeout);
			}
			// TODO can we implement that without a timeout?
			self.timeout = window.setTimeout(function() {
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			}, 13);
			event.preventDefault();
		});
	},

	_uiSpinnerHtml: function() {
		return '

';
	},

	_buttonHtml: function() {
		return '▲' +
				'▼';
	},

	_start: function(event) {
		if (!this.spinning && this._trigger('start', event, { value: this.options.value}) !== false) {
			if (!this.counter) {
				this.counter = 1;
			}
			this.spinning = true;
			return true;
		}
		return false;
	},

	// TODO tune repeat behaviour, see http://jsbin.com/aruki4/2 for reference
	_repeat: function(i, steps, event) {
		var self = this;
		i = i || 100;

		if (this.timer) {
			window.clearTimeout(this.timer);
		}

		this.timer = window.setTimeout(function() {
			self._repeat(self.options.incremental && self.counter > 20 ? 20 : i, steps, event);
		}, i);

		self._spin(steps*self.options.step, event);
	},

	_spin: function(step, event) {
		if (!this.counter) {
			this.counter = 1;
		}

		var newVal = this.options.value + step * (this.options.incremental && this.counter > 100
			? this.counter > 200
				? 100
				: 10
			: 1);

		// cancelable
		if (this._trigger('spin', event, { value: newVal }) !== false) {
			this.value(newVal);
			this.counter++;
		}
	},

	_stop: function(event) {
		this.counter = 0;
		if (this.timer) {
			window.clearTimeout(this.timer);
		}
		this.element[0].focus();
		this.spinning = false;
		this._trigger('stop', event);
	},

	_change: function(event) {
		this._trigger('change', event);
	},

	_setOption: function(key, value) {
		if (key == 'value') {
			value = this._parse(value);
			if (value < this.options.min) {
				value = this.options.min;
			}
			if (value > this.options.max) {
				value = this.options.max;
			}
		}
		$.Widget.prototype._setOption.call( this, key, value );
		this._afterSetData(key, value);
	},

	_afterSetData: function(key, value) {
		switch(key) {
			case 'value':
				this._format(this.options.value);
			case 'max':
			case 'min':
			case 'step':
				this._aria();
		}
	},

	_aria: function() {
		// TODO remove check, as soon as this method doesn't get called anymore before uiSpinner is initalized
		this.uiSpinner && this.uiSpinner
				.attr('aria-valuemin', this.options.min)
				.attr('aria-valuemax', this.options.max)
				.attr('aria-valuenow', this.options.value);
	},

	_parse: function(val) {
		var input = val;
		if (typeof val == 'string') {
			// special case for currency formatting until Globalization handles currencies
			if (this.options.numberformat == "C" && window.Globalization) {
				// parseFloat should accept number format, including currency
				var culture = Globalization.culture || Globalization.cultures['default'];
				val = val.replace(culture.numberFormat.currency.symbol, "");
			}
			val = window.Globalization && this.options.numberformat ? Globalization.parseFloat(val) : +val;
		}
		return isNaN(val) ? null : val;
	},

	_format: function(num) {
		this.element.val( window.Globalization && this.options.numberformat ? Globalization.format(num, this.options.numberformat) : num );
	},

	destroy: function() {
		if ($.fn.mousewheel) {
			this.element.unmousewheel();
		}

		this.element
			.removeClass('ui-spinner-input')
			.removeAttr('disabled')
			.removeAttr('autocomplete')
			.removeData('spinner')
			.unbind(".spinner");

		this.uiSpinner.replaceWith(this.element);
	},

	enable: function() {
		this.element
			.removeAttr('disabled')
			.parent()
				.removeClass('ui-spinner-disabled ui-state-disabled');
		this.options.disabled = false;
		this.buttons.button("enable");
	},

	disable: function() {
		this.element
			.attr('disabled', true)
			.parent()
				.addClass('ui-spinner-disabled ui-state-disabled');
		this.options.disabled = true;
		this.buttons.button("disable");
	},

	stepUp: function(steps) {
		this._spin((steps || 1) * this.options.step, null);
		return this;
	},

	stepDown: function(steps) {
		this._spin((steps || 1) * -this.options.step, null);
		return this;
	},

	pageUp: function(pages) {
		return this.stepUp((pages || 1) * pageModifier);
	},

	pageDown: function(pages) {
		return this.stepDown((pages || 1) * pageModifier);
	},

	value: function(newVal) {
		if (!arguments.length) {
			return this.options.value;
		}
		this._setOption('value', newVal);
	},

	widget: function() {
		return this.uiSpinner;
	}
});

})(jQuery);
<commit_msg>Slider: Improve destroy method<commit_after>/*
 * jQuery UI Spinner @VERSION
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Spinner
 *
 * Depends:
 *  jquery.ui.core.js
 *  jquery.ui.widget.js
 */
(function($) {

// shortcut constants
var pageModifier = 10;

$.widget('ui.spinner', {
	options: {
		incremental: true,
		max: Number.MAX_VALUE,
		min: -Number.MAX_VALUE,
		numberformat: null,
		step: 1,
		value: null
	},

	_create: function() {
		// html5 attributes initalization
		// TODO refactor
		var min = this.element.attr("min");
		if (typeof min == "string" && min.length > 0) {
			this.options.min = this._parse(min);
		}
		var max = this.element.attr("max");
		if (typeof max == "string" && max.length > 0) {
			this.options.max = this._parse(max);
		}
		var step = this.element.attr("step");
		if (typeof step == "string" && step.length > 0) {
			this.options.step = this._parse(step);
		}
		this.value(this.options.value !== null ? this.options.value : this.element.val() || 0);
		this._draw();
		this._mousewheel();
		this._aria();
	},

	_draw: function() {
		var self = this,
			options = self.options;

		var uiSpinner = this.uiSpinner = self.element
			.addClass('ui-spinner-input')
			.attr('autocomplete', 'off')
			.wrap(self._uiSpinnerHtml())
			.parent()
				// add buttons
				.append(self._buttonHtml())
				// add behaviours
				.hover(function() {
					if (!options.disabled) {
						$(this).addClass('ui-state-hover');
					}
					self.hovered = true;
				}, function() {
					$(this).removeClass('ui-state-hover');
					self.hovered = false;
				});

		// TODO: need a better way to exclude IE8 without resorting to $.browser.version
		// fix inline-block issues for IE. Since IE8 supports inline-block we need to exclude it.
		if (!$.support.opacity && uiSpinner.css('display') == 'inline-block' && $.browser.version < 8) {
			uiSpinner.css('display', 'inline');
		}

		this.element
			.bind('keydown.spinner', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self._start(event)) {
					return self._keydown(event);
				}
				return true;
			})
			.bind('keyup.spinner', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			})
			.bind('focus.spinner', function() {
				uiSpinner.addClass('ui-state-active');
				self.focused = true;
			})
			.bind('blur.spinner', function(event) {
				self.value(self.element.val());
				if (!self.hovered) {
					uiSpinner.removeClass('ui-state-active');
				}
				self.focused = false;
			});

		// button bindings
		this.buttons = uiSpinner.find('.ui-spinner-button')
			.attr("tabIndex", -1)
			.button()
			.first()
				.removeClass("ui-corner-all")
			.end()
			.last()
				.removeClass("ui-corner-all")
			.end()
			.bind('mousedown', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self._start(event) === false) {
					return false;
				}
				self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);
			})
			.bind('mouseup', function(event) {
				if (self.options.disabled) {
					return;
				}
				if (self.counter == 1) {
					self._spin(($(this).hasClass('ui-spinner-up') ? 1 : -1) * self.options.step, event);
				}
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			})
			.bind("mouseenter", function() {
				if (self.options.disabled) {
					return;
				}
				// button will add ui-state-active if mouse was down while mouseleave and kept down
				if ($(this).hasClass("ui-state-active")) {
					if (self._start(event) === false) {
						return false;
					}
					self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);
				}
			})
			.bind("mouseleave", function() {
				if (self.timer && self.spinning) {
					self._stop(event);
					self._change(event);
				}
			});

		// disable spinner if element was already disabled
		if (options.disabled) {
			this.disable();
		}
	},

	_keydown: function(event) {
		var o = this.options,
			KEYS = $.ui.keyCode;

		switch (event.keyCode) {
		case KEYS.UP:
			this._repeat(null, 1, event);
			return false;
		case KEYS.DOWN:
			this._repeat(null, -1, event);
			return false;
		case KEYS.PAGE_UP:
			this._repeat(null, pageModifier, event);
			return false;
		case KEYS.PAGE_DOWN:
			this._repeat(null, -pageModifier, event);
			return false;

		case KEYS.ENTER:
			this.value(this.element.val());
		}

		return true;
	},

	_mousewheel: function() {
		var self = this;
		this.element.bind("mousewheel.spinner", function(event, delta) {
			if (self.options.disabled) {
				return;
			}
			if (!self._start(event)) {
				return false;
			}
			self._spin((delta > 0 ? 1 : -1) * self.options.step, event);
			if (self.timeout) {
				window.clearTimeout(self.timeout);
			}
			// TODO can we implement that without a timeout?
			self.timeout = window.setTimeout(function() {
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			}, 13);
			event.preventDefault();
		});
	},

	_uiSpinnerHtml: function() {
		return '

';
	},

	_buttonHtml: function() {
		return '▲' +
				'▼';
	},

	_start: function(event) {
		if (!this.spinning && this._trigger('start', event, { value: this.options.value}) !== false) {
			if (!this.counter) {
				this.counter = 1;
			}
			this.spinning = true;
			return true;
		}
		return false;
	},

	// TODO tune repeat behaviour, see http://jsbin.com/aruki4/2 for reference
	_repeat: function(i, steps, event) {
		var self = this;
		i = i || 100;

		if (this.timer) {
			window.clearTimeout(this.timer);
		}

		this.timer = window.setTimeout(function() {
			self._repeat(self.options.incremental && self.counter > 20 ? 20 : i, steps, event);
		}, i);

		self._spin(steps*self.options.step, event);
	},

	_spin: function(step, event) {
		if (!this.counter) {
			this.counter = 1;
		}

		var newVal = this.options.value + step * (this.options.incremental && this.counter > 100
			? this.counter > 200
				? 100
				: 10
			: 1);

		// cancelable
		if (this._trigger('spin', event, { value: newVal }) !== false) {
			this.value(newVal);
			this.counter++;
		}
	},

	_stop: function(event) {
		this.counter = 0;
		if (this.timer) {
			window.clearTimeout(this.timer);
		}
		this.element[0].focus();
		this.spinning = false;
		this._trigger('stop', event);
	},

	_change: function(event) {
		this._trigger('change', event);
	},

	_setOption: function(key, value) {
		if (key == 'value') {
			value = this._parse(value);
			if (value < this.options.min) {
				value = this.options.min;
			}
			if (value > this.options.max) {
				value = this.options.max;
			}
		}
		$.Widget.prototype._setOption.call( this, key, value );
		this._afterSetData(key, value);
	},

	_afterSetData: function(key, value) {
		switch(key) {
			case 'value':
				this._format(this.options.value);
			case 'max':
			case 'min':
			case 'step':
				this._aria();
		}
	},

	_aria: function() {
		// TODO remove check, as soon as this method doesn't get called anymore before uiSpinner is initalized
		this.uiSpinner && this.uiSpinner
				.attr('aria-valuemin', this.options.min)
				.attr('aria-valuemax', this.options.max)
				.attr('aria-valuenow', this.options.value);
	},

	_parse: function(val) {
		var input = val;
		if (typeof val == 'string') {
			// special case for currency formatting until Globalization handles currencies
			if (this.options.numberformat == "C" && window.Globalization) {
				// parseFloat should accept number format, including currency
				var culture = Globalization.culture || Globalization.cultures['default'];
				val = val.replace(culture.numberFormat.currency.symbol, "");
			}
			val = window.Globalization && this.options.numberformat ? Globalization.parseFloat(val) : +val;
		}
		return isNaN(val) ? null : val;
	},

	_format: function(num) {
		this.element.val( window.Globalization && this.options.numberformat ? Globalization.format(num, this.options.numberformat) : num );
	},

	destroy: function() {
		this.element
			.removeClass('ui-spinner-input')
			.removeAttr('disabled')
			.removeAttr('autocomplete');
		$.Widget.prototype.destroy.call( this );
		this.uiSpinner.replaceWith(this.element);
	},

	enable: function() {
		this.element
			.removeAttr('disabled')
			.parent()
				.removeClass('ui-spinner-disabled ui-state-disabled');
		this.options.disabled = false;
		this.buttons.button("enable");
	},

	disable: function() {
		this.element
			.attr('disabled', true)
			.parent()
				.addClass('ui-spinner-disabled ui-state-disabled');
		this.options.disabled = true;
		this.buttons.button("disable");
	},

	stepUp: function(steps) {
		this._spin((steps || 1) * this.options.step, null);
		return this;
	},

	stepDown: function(steps) {
		this._spin((steps || 1) * -this.options.step, null);
		return this;
	},

	pageUp: function(pages) {
		return this.stepUp((pages || 1) * pageModifier);
	},

	pageDown: function(pages) {
		return this.stepDown((pages || 1) * pageModifier);
	},

	value: function(newVal) {
		if (!arguments.length) {
			return this.options.value;
		}
		this._setOption('value', newVal);
	},

	widget: function() {
		return this.uiSpinner;
	}
});

})(jQuery);
<|endoftext|>


<commit_before>const btcProof = require('../index'),
  assert = require('assert');

const BLOCK_100K = {
  txs: [
    '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87',
    'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4',
    '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4',
    'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'
  ]
},
  BLOCK_106022 = {
    txs: [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ]
  };

describe('getProof', function() {
  describe('for block 100k', function() {
    it('tx[0]', function() {
      const txs = BLOCK_100K.txs;

      // >>> i = '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4'.decode('hex')[::-1]
      // >>> j = 'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'.decode('hex')[::-1]
      // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
      // '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49'
      const hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        expProof = [{ hash: txs[1], path: 2 }, { hash: hRight, path: 2 }];

      var proof = btcProof.getProof(txs, 0);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[1]', function() {
      const txs = BLOCK_100K.txs,
        hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        expProof = [{ hash: txs[0], path: 1 }, { hash: hRight, path: 2 }];

      var proof = btcProof.getProof(txs, 1);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[2]', function() {
      const txs = BLOCK_100K.txs;

      // >>> i = '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87'.decode('hex')[::-1]
      // >>> j = 'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4'.decode('hex')[::-1]
      // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
      // 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815'
      const hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        expProof = [{ hash: txs[3], path: 2 }, { hash: hLeft, path: 1 }];

      var proof = btcProof.getProof(txs, 2);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[3]', function() {
      const txs = BLOCK_100K.txs,
        hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        expProof = [{ hash: txs[2], path: 1 }, { hash: hLeft, path: 1 }];

      var proof = btcProof.getProof(txs, 3);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      expProof = [
        { hash: txs[1], path: 2 },
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2 },
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2 }
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });
});

describe('getMerkleRoot', function() {
  it('should return merkle root of block 100k', function() {
    const txs = BLOCK_100K.txs,
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 100k-1 (odd num of tx)', function() {
    const txs = [
      '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90'
    ],
      expMerkle = '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 106022', function() {
    const txs = BLOCK_106022.txs,
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });
});

describe('getTxMerkle', function() {
  it('for block 100k tx[0]', function() {
    const txs = BLOCK_100K.txs,
      hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
      proof = [{ hash: txs[1], path: 2 }, { hash: hRight, path: 2 }],
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      proof = [
        { hash: txs[1], path: 2 },
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2 },
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2 }
      ],
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });
});
<commit_msg>compute merkles for 4 combos<commit_after>const btcProof = require('../index'),
  assert = require('assert');

const BLOCK_100K = {
  txs: [
    '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87',
    'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4',
    '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4',
    'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'
  ]
},
  BLOCK_106022 = {
    txs: [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ]
  };

describe('getProof', function() {
  describe('for block 100k', function() {
    it('tx[0]', function() {
      const txs = BLOCK_100K.txs;

      // >>> i = '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4'.decode('hex')[::-1]
      // >>> j = 'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'.decode('hex')[::-1]
      // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
      // '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49'
      const hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        expProof = [{ hash: txs[1], path: 2 }, { hash: hRight, path: 2 }];

      var proof = btcProof.getProof(txs, 0);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[1]', function() {
      const txs = BLOCK_100K.txs,
        hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        expProof = [{ hash: txs[0], path: 1 }, { hash: hRight, path: 2 }];

      var proof = btcProof.getProof(txs, 1);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[2]', function() {
      const txs = BLOCK_100K.txs;

      // >>> i = '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87'.decode('hex')[::-1]
      // >>> j = 'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4'.decode('hex')[::-1]
      // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
      // 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815'
      const hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        expProof = [{ hash: txs[3], path: 2 }, { hash: hLeft, path: 1 }];

      var proof = btcProof.getProof(txs, 2);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });

    it('tx[3]', function() {
      const txs = BLOCK_100K.txs,
        hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        expProof = [{ hash: txs[2], path: 1 }, { hash: hLeft, path: 1 }];

      var proof = btcProof.getProof(txs, 3);
      assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
    });
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      expProof = [
        { hash: txs[1], path: 2 },
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2 },
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2 }
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });
});

describe('getMerkleRoot', function() {
  it('should return merkle root of block 100k', function() {
    const txs = BLOCK_100K.txs,
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 100k-1 (odd num of tx)', function() {
    const txs = [
      '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90'
    ],
      expMerkle = '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 106022', function() {
    const txs = BLOCK_106022.txs,
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });
});

describe('getTxMerkle', function() {
  describe('for block 100k', function() {
    it('tx[0]', function() {
      const txs = BLOCK_100K.txs,
        hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        proof = [{ hash: txs[1], path: 2 }, { hash: hRight, path: 2 }],
        expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

      var merkle = btcProof.getTxMerkle(txs[0], proof);
      assert.strictEqual(merkle, expMerkle);
    });

    it('tx[1]', function() {
      const txs = BLOCK_100K.txs,
        hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
        proof = [{ hash: txs[0], path: 1 }, { hash: hRight, path: 2 }],
        expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

      var merkle = btcProof.getTxMerkle(txs[1], proof);
      assert.strictEqual(merkle, expMerkle);
    });

    it('tx[2]', function() {
      const txs = BLOCK_100K.txs,
        hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        proof = [{ hash: txs[3], path: 2 }, { hash: hLeft, path: 1 }],
        expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

      var merkle = btcProof.getTxMerkle(txs[2], proof);
      assert.strictEqual(merkle, expMerkle);
    });

    it('tx[3]', function() {
      const txs = BLOCK_100K.txs,
        hLeft = 'ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815',
        proof = [{ hash: txs[2], path: 1 }, { hash: hLeft, path: 1 }],
        expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

      var merkle = btcProof.getTxMerkle(txs[3], proof);
      assert.strictEqual(merkle, expMerkle);
    });
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      proof = [
        { hash: txs[1], path: 2 },
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2 },
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2 }
      ],
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });
});
<|endoftext|>


<commit_before>// adopted from: https://github.com/lepture/editor/blob/master/src/intro.js#L343
// inspired by: Jon Schlinkert -- wordcount <https://github.com/jonschlinkert/wordcount>
// enhanced by: Charlike Mike Reagent adding cyrillic: \u0400-\u04FF - to the end of groups

function countWords (data) {
  var pattern = /[a-zA-Z0-9_\u0392-\u03c9\u0400-\u04FF]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|\w+/g
  var m = data.match(pattern)

  var count = 0

  if( m === null ) return count

  var i = -1
  var len = m.length

  while (++i < len) {
    if (m[i].charCodeAt(0) >= 0x4E00) count += m[i].length
    else count += 1
  }

  return count
}

module.exports = countWords
<commit_msg>update string/countWords.js<commit_after>// adopted from: https://github.com/lepture/editor/blob/master/src/intro.js#L343
// inspired by: Jon Schlinkert -- wordcount <https://github.com/jonschlinkert/wordcount>
// enhanced by: Charlike Mike Reagent adding cyrillic: \u0400-\u04FF - to the end of groups

function countWords (data) {
  var pattern = /[a-zA-Z0-9_\u0392-\u03c9\u0400-\u04FF]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|\w+/g
  var m = data.match(pattern)

  var count = 0

  if (m === null) return count

  var i = -1
  var len = m.length

  while (++i < len) {
    if (m[i].charCodeAt(0) >= 0x4E00) count += m[i].length
    else count += 1
  }

  return count
}

module.exports = countWords
<|endoftext|>


<commit_before>"use strict";

treeherder.factory('PhAlerts', [
    '$http', '$q', 'thServiceDomain', 'ThOptionCollectionModel', 'PhSeries',
    'phAlertSummaryStatusMap', 'phAlertStatusMap', 'thPerformanceBranches',
    function($http, $q, thServiceDomain, ThOptionCollectionModel, PhSeries,
             phAlertSummaryStatusMap, phAlertStatusMap, thPerformanceBranches) {

        var Alert = function(alertData, optionCollectionMap) {
            _.assign(this, alertData);
            this.title = PhSeries.getSeriesName(
                this.series_signature, optionCollectionMap,
                {includePlatformInName: true});
        };
        Alert.prototype.getStatusText = function() {
            return _.result(_.find(phAlertStatusMap, {id: this.status}),
                            'text');
        };
        Alert.prototype.getGraphsURL = function(timeRange, alertRepository,
                                                performanceFrameworkId) {
            var signature = this.series_signature.signature_hash;
            var url = "#/graphs?timerange=" + timeRange +
                "&series=[" + [alertRepository, signature, 1] + "]" +
                "&selected=[" + [alertRepository, signature,] + "]";

            // for talos only, automatically add related branches
            if (performanceFrameworkId === 1) {
                _.forEach(thPerformanceBranches, function(performanceBranch) {
                    if (performanceBranch !== alertRepository) {
                        url += "&series=[" + [performanceBranch, signature, 0] + "]";
                    }
                });
            }

            return url;
        };
        Alert.prototype.getSubtestsURL = function(alertSummary) {
            var endpoint = '#/comparesubtest';
            var urlParameters = {
                framework: alertSummary.framework,
                originalProject: alertSummary.repository,
                originalSignature: this.series_signature.signature_hash,
                newProject: alertSummary.repository,
                newSignature: this.series_signature.signature_hash,
            };
            if (alertSummary.prevResultSetMetadata) {
                urlParameters.originalRevision = alertSummary.prevResultSetMetadata.revision;
            }
            if (alertSummary.prevResultSetMetadata) {
                urlParameters.newRevision = alertSummary.resultSetMetadata.revision;
            }

            return endpoint + '?' + _.map(urlParameters, function(v, k) {return k + '=' + v;}).join('&');
        };
        Alert.prototype.modify = function(modification) {
            return $http.put(thServiceDomain +
                             '/api/performance/alert/' + this.id + '/',
                             modification);
        };
        _.forEach(phAlertStatusMap, function(status) {
            Alert.prototype['is' + _.capitalize(status.text)] = function() {
                return this.status === status.id;
            };
        });

        var AlertSummary = function(alertSummaryData, optionCollectionMap) {
            _.assign(this, alertSummaryData);
            this._initializeAlerts(optionCollectionMap);
        };
        _.forEach(phAlertSummaryStatusMap, function(status) {
            AlertSummary.prototype['is' + _.capitalize(status.text)] = function() {
                return this.status === status.id;
            };
            AlertSummary.prototype['mark' + _.capitalize(status.text)] = function() {
                this.updateStatus(status);
            };
        });
        AlertSummary.prototype.getTextualSummary = function() {
            var resultStr = "";
            var improved = _.filter(this.alerts, function(alert) {return !alert.is_regression && alert.visible;});
            var regressed = _.filter(this.alerts, function(alert) {return alert.is_regression && alert.visible;});
            if (regressed.length > 0) {
                resultStr += "Summary of tests that regressed:\n\n" +
                             _.map(regressed, function(alert) {
                                 return "  " + alert.title + " - " + alert.amount_pct + "% worse";
                             }).join('\n') + "\n";
            }
            if (improved.length > 0) {
                resultStr += "Summary of tests that improved:\n\n" +
                             _.map(improved, function(alert) {
                                 return "  " + alert.title + " - " + alert.amount_pct + "% better";
                             }).join('\n') + "\n";
            }
            return resultStr;
        };
        AlertSummary.prototype.isResolved = function() {
            return this.isFixed() || this.isWontfix() || this.isBackedout();
        };
        AlertSummary.prototype._initializeAlerts = function(optionCollectionMap) {
            // this function converts the representation returned by the perfherder
            // api into a representation more suited for display in the UI

            // just treat related (reassigned or downstream) alerts as one
            // big block -- we'll display in the UI depending on their content
            this.alerts = _.map(this.alerts.concat(this.related_alerts),
                function(alertData) {
                    return new Alert(alertData, optionCollectionMap);
                });
        };
        AlertSummary.prototype.updateStatus = function(newStatus) {
            var alertSummary = this;
            return $http.put(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/',
                             { status: newStatus.id }).then(function() {
                                 alertSummary.status = newStatus.id;
                             });
        };
        AlertSummary.prototype.update = function() {
            var alertSummary = this;
            return $http.get(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/').then(
                                 function(response) {
                                     return ThOptionCollectionModel.getMap().then(
                                         function(optionCollectionMap) {
                                             _.assign(alertSummary, response.data);
                                             alertSummary._initializeAlerts(
                                                 optionCollectionMap);
                                         });
                                 });
        };
        AlertSummary.prototype.getTitle = function(options) {
            var title;

            // we should never include downstream alerts in the description
            var alertSummary = this;
            var alertsInSummary = _.filter(this.alerts, function(alert) {
                return (alert.status !== phAlertStatusMap.DOWNSTREAM.id ||
                        alert.summary_id === alertSummary.id);
            });

            // figure out if there are any regressions -- if there are,
            // the summary should only incorporate those. if there
            // aren't, then use all of them (that aren't downstream,
            // see above)
            if (_.any(_.pluck(alertsInSummary, 'is_regression'))) {
                alertsInSummary = _.filter(alertsInSummary, 'is_regression');
            }

            if (alertsInSummary.length > 1) {
                title = _.min(_.pluck(alertsInSummary, 'amount_pct')) + " - " +
                    _.max(_.pluck(alertsInSummary, 'amount_pct')) + "%";
            } else if (alertsInSummary.length === 1) {
                title = alertsInSummary[0].amount_pct + "%";
            } else {
                title = "Empty alert";
            }
            // add test info
            title += " " + _.uniq(
                _.map(alertsInSummary, function(a) {
                    return PhSeries.getTestName(a.series_signature, { abbreviate:true });
                })).sort().join(' / ');
            // add platform info
            title += " (" + _.uniq(
                _.map(alertsInSummary, function(a) {
                    return a.series_signature.machine_platform;
                })).sort().join(', ') + ')';
            return title;
        };
        AlertSummary.prototype.assignBug = function(bugNumber) {
            var alertSummary = this;
            return $http.put(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/',
                             { bug_number: bugNumber }).then(function() {
                                 return alertSummary.update();
                             });
        };
        AlertSummary.prototype.modifySelectedAlerts = function(modification) {
            this.allSelected = false;

            return $q.all(_.where(this.alerts, {'selected': true}).map(
                function(selectedAlert) {
                    selectedAlert.selected = false;
                    return selectedAlert.modify(modification);
                }));
        };
        AlertSummary.prototype.getStatusText = function() {
            return _.find(phAlertSummaryStatusMap, { id: this.status }).text;
        };

        function _getAlertSummary(id) {
            // get a specific alert summary
            // in order to cancel the http request, a canceller must be used
            // http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx
            var canceller = $q.defer();
            var promise = ThOptionCollectionModel.getMap().then(
                function(optionCollectionMap) {
                    return $http.get(thServiceDomain + '/api/performance/alertsummary/' + id + '/',
                                    {timeout : canceller.promise}).then(
                                        function(response) {
                                            return new AlertSummary(response.data,
                                                                    optionCollectionMap);
                                        }
                    );
                }
            );
            promise.cancel = function() {
                canceller.resolve();
            };
            return promise;
        }

        return {
            getAlertSummary: _getAlertSummary,
            getAlertSummaryTitle: function(id) {
                var request = _getAlertSummary(id);
                var promise = request.then(function(alertSummary) {
                    return alertSummary.getTitle();
                });
                promise.cancel = request.cancel;
                return promise;
            },
            getAlertSummaries: function(options) {
                var href;
                if (!options || !options.href) {
                    href = thServiceDomain + '/api/performance/alertsummary/';

                    // add filter parameters for status and framework
                    var params = [];
                    if (options && !_.isUndefined(options.statusFilter) &&
                        options.statusFilter !== (-1)) {
                        params[params.length] = ("status=" + options.statusFilter);
                    }
                    if (options && !_.isUndefined(options.frameworkFilter)) {
                        params[params.length] = ("framework=" + options.frameworkFilter);
                    }
                    if (options && !_.isUndefined(options.seriesSignature)) {
                        params[params.length] = ("alerts__series_signature__signature_hash=" +
                                                 options.seriesSignature);
                    }
                    if (options && !_.isUndefined(options.repository)) {
                        params[params.length] = ("repository=" +
                                                 options.repository);
                    }
                    if (options && !_.isUndefined(options.page)) {
                        params[params.length] = ("page=" + options.page);
                    }

                    if (params.length) {
                        href += "?" + params.join("&");
                    }
                } else {
                    href = options.href;
                    // status filter already in url if using pregenerated url
                }

                return ThOptionCollectionModel.getMap().then(
                    function(optionCollectionMap) {
                        return $http.get(href).then(function(response) {
                            return {
                                results: _.map(response.data.results, function(alertSummaryData) {
                                    return new AlertSummary(alertSummaryData, optionCollectionMap);
                                }),
                                next: response.data.next,
                                count: response.data.count,
                            };
                        });
                    });
            },
            createAlert: function(data) {
                return $http.post(thServiceDomain + '/api/performance/alertsummary/', {
                    repository_id: data.project.id,
                    framework_id: data.series.frameworkId,
                    result_set_id: data.resultSetId,
                    prev_result_set_id: data.prevResultSetId
                }).then(function(response) {
                    var newAlertSummaryId = response.data.alert_summary_id;
                    return $http.post(thServiceDomain + '/api/performance/alert/', {
                        summary_id: newAlertSummaryId,
                        signature_id: data.series.id
                    }).then(function() {
                        return newAlertSummaryId;
                    });
                });
            }
        };
    }]);
<commit_msg>Bug 1270524 - Improve formatting of textual description of alert summary (#1659)<commit_after>"use strict";

treeherder.factory('PhAlerts', [
    '$http', '$q', 'thServiceDomain', 'ThOptionCollectionModel', 'PhSeries',
    'phAlertSummaryStatusMap', 'phAlertStatusMap', 'thPerformanceBranches',
    function($http, $q, thServiceDomain, ThOptionCollectionModel, PhSeries,
             phAlertSummaryStatusMap, phAlertStatusMap, thPerformanceBranches) {

        var Alert = function(alertData, optionCollectionMap) {
            _.assign(this, alertData);
            this.title = PhSeries.getSeriesName(
                this.series_signature, optionCollectionMap,
                {includePlatformInName: true});
        };
        Alert.prototype.getStatusText = function() {
            return _.result(_.find(phAlertStatusMap, {id: this.status}),
                            'text');
        };
        Alert.prototype.getGraphsURL = function(timeRange, alertRepository,
                                                performanceFrameworkId) {
            var signature = this.series_signature.signature_hash;
            var url = "#/graphs?timerange=" + timeRange +
                "&series=[" + [alertRepository, signature, 1] + "]" +
                "&selected=[" + [alertRepository, signature,] + "]";

            // for talos only, automatically add related branches
            if (performanceFrameworkId === 1) {
                _.forEach(thPerformanceBranches, function(performanceBranch) {
                    if (performanceBranch !== alertRepository) {
                        url += "&series=[" + [performanceBranch, signature, 0] + "]";
                    }
                });
            }

            return url;
        };
        Alert.prototype.getSubtestsURL = function(alertSummary) {
            var endpoint = '#/comparesubtest';
            var urlParameters = {
                framework: alertSummary.framework,
                originalProject: alertSummary.repository,
                originalSignature: this.series_signature.signature_hash,
                newProject: alertSummary.repository,
                newSignature: this.series_signature.signature_hash,
            };
            if (alertSummary.prevResultSetMetadata) {
                urlParameters.originalRevision = alertSummary.prevResultSetMetadata.revision;
            }
            if (alertSummary.prevResultSetMetadata) {
                urlParameters.newRevision = alertSummary.resultSetMetadata.revision;
            }

            return endpoint + '?' + _.map(urlParameters, function(v, k) {return k + '=' + v;}).join('&');
        };
        Alert.prototype.modify = function(modification) {
            return $http.put(thServiceDomain +
                             '/api/performance/alert/' + this.id + '/',
                             modification);
        };
        _.forEach(phAlertStatusMap, function(status) {
            Alert.prototype['is' + _.capitalize(status.text)] = function() {
                return this.status === status.id;
            };
        });

        var AlertSummary = function(alertSummaryData, optionCollectionMap) {
            _.assign(this, alertSummaryData);
            this._initializeAlerts(optionCollectionMap);
        };
        _.forEach(phAlertSummaryStatusMap, function(status) {
            AlertSummary.prototype['is' + _.capitalize(status.text)] = function() {
                return this.status === status.id;
            };
            AlertSummary.prototype['mark' + _.capitalize(status.text)] = function() {
                this.updateStatus(status);
            };
        });
        AlertSummary.prototype.getTextualSummary = function() {
            var resultStr = "";
            var improved = _.filter(this.alerts, function(alert) {return !alert.is_regression && alert.visible;});
            var regressed = _.filter(this.alerts, function(alert) {return alert.is_regression && alert.visible;});
            if (regressed.length > 0) {
                resultStr += "Summary of tests that regressed:\n\n" +
                             _.map(regressed, function(alert) {
                                 return "  " + alert.title + " - " + alert.amount_pct + "% worse";
                             }).join('\n') + "\n";
            }
            if (improved.length > 0) {
                // Add a newline if we displayed some regressions
                if (resultStr.length > 0) {
                    resultStr += "\n";
                }
                resultStr += "Summary of tests that improved:\n\n" +
                             _.map(improved, function(alert) {
                                 return "  " + alert.title + " - " + alert.amount_pct + "% better";
                             }).join('\n') + "\n";
            }
            return resultStr;
        };
        AlertSummary.prototype.isResolved = function() {
            return this.isFixed() || this.isWontfix() || this.isBackedout();
        };
        AlertSummary.prototype._initializeAlerts = function(optionCollectionMap) {
            // this function converts the representation returned by the perfherder
            // api into a representation more suited for display in the UI

            // just treat related (reassigned or downstream) alerts as one
            // big block -- we'll display in the UI depending on their content
            this.alerts = _.map(this.alerts.concat(this.related_alerts),
                function(alertData) {
                    return new Alert(alertData, optionCollectionMap);
                });
        };
        AlertSummary.prototype.updateStatus = function(newStatus) {
            var alertSummary = this;
            return $http.put(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/',
                             { status: newStatus.id }).then(function() {
                                 alertSummary.status = newStatus.id;
                             });
        };
        AlertSummary.prototype.update = function() {
            var alertSummary = this;
            return $http.get(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/').then(
                                 function(response) {
                                     return ThOptionCollectionModel.getMap().then(
                                         function(optionCollectionMap) {
                                             _.assign(alertSummary, response.data);
                                             alertSummary._initializeAlerts(
                                                 optionCollectionMap);
                                         });
                                 });
        };
        AlertSummary.prototype.getTitle = function(options) {
            var title;

            // we should never include downstream alerts in the description
            var alertSummary = this;
            var alertsInSummary = _.filter(this.alerts, function(alert) {
                return (alert.status !== phAlertStatusMap.DOWNSTREAM.id ||
                        alert.summary_id === alertSummary.id);
            });

            // figure out if there are any regressions -- if there are,
            // the summary should only incorporate those. if there
            // aren't, then use all of them (that aren't downstream,
            // see above)
            if (_.any(_.pluck(alertsInSummary, 'is_regression'))) {
                alertsInSummary = _.filter(alertsInSummary, 'is_regression');
            }

            if (alertsInSummary.length > 1) {
                title = _.min(_.pluck(alertsInSummary, 'amount_pct')) + " - " +
                    _.max(_.pluck(alertsInSummary, 'amount_pct')) + "%";
            } else if (alertsInSummary.length === 1) {
                title = alertsInSummary[0].amount_pct + "%";
            } else {
                title = "Empty alert";
            }
            // add test info
            title += " " + _.uniq(
                _.map(alertsInSummary, function(a) {
                    return PhSeries.getTestName(a.series_signature, { abbreviate:true });
                })).sort().join(' / ');
            // add platform info
            title += " (" + _.uniq(
                _.map(alertsInSummary, function(a) {
                    return a.series_signature.machine_platform;
                })).sort().join(', ') + ')';
            return title;
        };
        AlertSummary.prototype.assignBug = function(bugNumber) {
            var alertSummary = this;
            return $http.put(thServiceDomain +
                             '/api/performance/alertsummary/' + this.id + '/',
                             { bug_number: bugNumber }).then(function() {
                                 return alertSummary.update();
                             });
        };
        AlertSummary.prototype.modifySelectedAlerts = function(modification) {
            this.allSelected = false;

            return $q.all(_.where(this.alerts, {'selected': true}).map(
                function(selectedAlert) {
                    selectedAlert.selected = false;
                    return selectedAlert.modify(modification);
                }));
        };
        AlertSummary.prototype.getStatusText = function() {
            return _.find(phAlertSummaryStatusMap, { id: this.status }).text;
        };

        function _getAlertSummary(id) {
            // get a specific alert summary
            // in order to cancel the http request, a canceller must be used
            // http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx
            var canceller = $q.defer();
            var promise = ThOptionCollectionModel.getMap().then(
                function(optionCollectionMap) {
                    return $http.get(thServiceDomain + '/api/performance/alertsummary/' + id + '/',
                                    {timeout : canceller.promise}).then(
                                        function(response) {
                                            return new AlertSummary(response.data,
                                                                    optionCollectionMap);
                                        }
                    );
                }
            );
            promise.cancel = function() {
                canceller.resolve();
            };
            return promise;
        }

        return {
            getAlertSummary: _getAlertSummary,
            getAlertSummaryTitle: function(id) {
                var request = _getAlertSummary(id);
                var promise = request.then(function(alertSummary) {
                    return alertSummary.getTitle();
                });
                promise.cancel = request.cancel;
                return promise;
            },
            getAlertSummaries: function(options) {
                var href;
                if (!options || !options.href) {
                    href = thServiceDomain + '/api/performance/alertsummary/';

                    // add filter parameters for status and framework
                    var params = [];
                    if (options && !_.isUndefined(options.statusFilter) &&
                        options.statusFilter !== (-1)) {
                        params[params.length] = ("status=" + options.statusFilter);
                    }
                    if (options && !_.isUndefined(options.frameworkFilter)) {
                        params[params.length] = ("framework=" + options.frameworkFilter);
                    }
                    if (options && !_.isUndefined(options.seriesSignature)) {
                        params[params.length] = ("alerts__series_signature__signature_hash=" +
                                                 options.seriesSignature);
                    }
                    if (options && !_.isUndefined(options.repository)) {
                        params[params.length] = ("repository=" +
                                                 options.repository);
                    }
                    if (options && !_.isUndefined(options.page)) {
                        params[params.length] = ("page=" + options.page);
                    }

                    if (params.length) {
                        href += "?" + params.join("&");
                    }
                } else {
                    href = options.href;
                    // status filter already in url if using pregenerated url
                }

                return ThOptionCollectionModel.getMap().then(
                    function(optionCollectionMap) {
                        return $http.get(href).then(function(response) {
                            return {
                                results: _.map(response.data.results, function(alertSummaryData) {
                                    return new AlertSummary(alertSummaryData, optionCollectionMap);
                                }),
                                next: response.data.next,
                                count: response.data.count,
                            };
                        });
                    });
            },
            createAlert: function(data) {
                return $http.post(thServiceDomain + '/api/performance/alertsummary/', {
                    repository_id: data.project.id,
                    framework_id: data.series.frameworkId,
                    result_set_id: data.resultSetId,
                    prev_result_set_id: data.prevResultSetId
                }).then(function(response) {
                    var newAlertSummaryId = response.data.alert_summary_id;
                    return $http.post(thServiceDomain + '/api/performance/alert/', {
                        summary_id: newAlertSummaryId,
                        signature_id: data.series.id
                    }).then(function() {
                        return newAlertSummaryId;
                    });
                });
            }
        };
    }]);
<|endoftext|>


<commit_before>var express = require('express')
var router = express.Router()

var path = require('path')
var helper = require('./modules/helper')

// import controllers
var binding = require("./controllers/binding.js")

// getBaseInfo
router.use(express.query())
router.get('/info', function(req, res) {
	helper.getBaseInfo(req.query.code, function(err, baseInfoQuery){
        if(err){
            res.send(JSON.stringify(err))
        } else{
			var openId = JSON.stringify(baseInfoQuery).match(/openid=.+?&/).slice(7).slice(0, -1)
            res.redirect(req.query.state + '?openId=' + openId)
        }
	})
})

// bind
router.get('/binding', binding.page.index)
router.get('/api/binding/state', binding.api.state)
router.post('/api/binding/bind', binding.api.bind)

// FIXME 这里应该redirect到预定会议室页面
router.get('/reserve', function(req, res) {
	res.sendFile(path.join(__dirname + '/views/reserve.html'))
})

module.exports = router
<commit_msg>test info<commit_after>var express = require('express')
var router = express.Router()

var path = require('path')
var helper = require('./modules/helper')

// import controllers
var binding = require("./controllers/binding.js")

// getBaseInfo
router.use(express.query())
router.get('/info', function(req, res) {
	helper.getBaseInfo(req.query.code, function(err, baseInfoQuery){
        if(err){
            res.send(JSON.stringify(err))
        } else{
			var openId = JSON.stringify(baseInfoQuery).match(/openid=.+?&/)[0].slice(7).slice(0, -1)
            res.redirect(req.query.state + '?openId=' + openId)
        }
	})
})

// bind
router.get('/binding', binding.page.index)
router.get('/api/binding/state', binding.api.state)
router.post('/api/binding/bind', binding.api.bind)

// FIXME 这里应该redirect到预定会议室页面
router.get('/reserve', function(req, res) {
	res.sendFile(path.join(__dirname + '/views/reserve.html'))
})

module.exports = router
<|endoftext|>


<commit_before>/**
 * FlowObjectControl
 *
 * Renders an information field mentioning that this property can't be generated.
 */

import renderControls from '../../../../utils/renderControls';
import React from 'react';
import Label from '../../../common/Label';
import normalizeProps from './normalizeProps';
import randomValue from './randomValue';
import styles from '../ObjectControl/styles.css';

const FlowObjectControl = ({ label, propTypeData, value, onUpdate, nestedLevel }) => {
  const updatePropertyValues = (values) => {
    onUpdate({ value: values });
  };

  const normalizedPropsWithControls = normalizeProps(propTypeData.signature.properties);

  let controlWrapperClassName = styles.nestedControls;
  if (!label && nestedLevel > 0) {
    controlWrapperClassName = styles['nestedDeeperThanOneLevel--without-label'];
  } else if (nestedLevel > 0) {
    controlWrapperClassName = styles.nestedDeeperThanOneLevel;
  }

  return (

      {/* inside arrays there is no label for the object */}
      {(label) && (
         onUpdate({
            value: FlowObjectControl.randomValue(propTypeData),
          })}
        />
      )}

        {renderControls(normalizedPropsWithControls, value, updatePropertyValues, true)}

  );
};

FlowObjectControl.randomValue = randomValue;

export default FlowObjectControl;
<commit_msg>style FlowObjectControl<commit_after>/**
 * FlowObjectControl
 *
 * Renders an information field mentioning that this property can't be generated.
 */

import renderControls from '../../../../utils/renderControls';
import React from 'react';
import normalizeProps from './normalizeProps';
import randomValue from './randomValue';
import Row from '../../../form/Grid/Row';
import LeftColumn from '../../../form/Grid/LeftColumn';
import RightColumn from '../../../form/Grid/RightColumn';
import Label from '../../../form/Label';
import RandomButton from '../../../form/RandomButton';
import SettingsButton from '../../../form/SettingsButton';
import BaseSettings from '../../../form/BaseSettings';
import Dropdown from '../../../form/Dropdown';

class FlowObjectControl extends React.Component {

  state = {
    settingsActive: false,
  }

  onToggleSettings = () => {
    this.setState({
      settingsActive: !this.state.settingsActive,
    });
  }

  render() {
    const { label, propTypeData, value, onUpdate, nestedLevel, secondaryLabel } = this.props;

    const hasSettings = true;

    const updatePropertyValues = (values) => {
      onUpdate({ value: values });
    };

    const normalizedPropsWithControls = normalizeProps(propTypeData.signature.properties);

    return (
      <Row>
        <LeftColumn nestedLevel={nestedLevel}>
          {/* inside arrays there is no label for the object */}
          {(label) && (

          )}
        </LeftColumn>
        <RightColumn>

            {hasSettings && <Dropdown
              active={this.state.settingsActive}
            >
              <BaseSettings onChange={onUpdate} />
            </Dropdown>}
            <SettingsButton
              groupType="left"
              onClick={this.onToggleSettings}
            />
            <RandomButton
              onClick={() => onUpdate({ value: FlowObjectControl.randomValue(propTypeData) })}
            />

        </RightColumn>
        <Row>
          {renderControls(
            normalizedPropsWithControls,
            value,
            updatePropertyValues,
            nestedLevel + 1
          )}
        </Row>
      </Row>
    );
  }
}

FlowObjectControl.randomValue = randomValue;

export default FlowObjectControl;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule React
 */

module.exports = require('react');
<commit_msg>Require react-for-atom instead of react.<commit_after>/**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule React
 */

module.exports = require('react-for-atom');
<|endoftext|>


<commit_before>var chessground = require('chessground');
var classSet = chessground.util.classSet;
var game = require('game').game;
var status = require('game').status;
var partial = chessground.util.partial;
var router = require('game').router;
var m = require('mithril');

function analysisBoardOrientation(data) {
  if (data.game.variant.key === 'racingKings') {
    return 'white';
  } else {
    return data.player.color;
  }
}

module.exports = {
  standard: function(ctrl, condition, icon, hint, socketMsg, onclick) {
    // disabled if condition callback is provied and is falsy
    var enabled = !condition || condition(ctrl.data);
    return m('button', {
      class: 'button hint--bottom ' + socketMsg + classSet({
        ' disabled': !enabled
      }),
      'data-hint': ctrl.trans(hint),
      onclick: enabled ? onclick || partial(ctrl.socket.send, socketMsg, null) : null
    }, m('span', {
      'data-icon': icon
    }));
  },
  forceResign: function(ctrl) {
    if (!ctrl.data.opponent.ai && ctrl.data.clock && ctrl.data.opponent.isGone && game.resignable(ctrl.data))
      return m('div.force_resign_zone', [
        ctrl.trans('theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim'),
        m('br'),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'resign-force', null),
        }, ctrl.trans('forceResignation')),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'draw-force', null),
        }, ctrl.trans('forceDraw'))
      ]);
  },
  resignConfirm: function(ctrl) {
    return m('div.resign_confirm', [
      m('button.button.yes.active.hint--bottom', {
        'data-hint': ctrl.trans('resign'),
        onclick: partial(ctrl.resign, true)
      }, m('span', {
        'data-icon': 'b'
      })), m('button.button.no.hint--bottom', {
        'data-hint': ctrl.trans('cancel'),
        onclick: partial(ctrl.resign, false)
      }, m('span', {
        'data-icon': 'L'
      }))
    ]);
  },
  threefoldClaimDraw: function(ctrl) {
    if (ctrl.data.game.threefold) return m('div#claim_draw_zone', [
      ctrl.trans('threefoldRepetition'),
      m.trust(' '),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'draw-claim', null)
      }, ctrl.trans('claimADraw'))
    ]);
  },
  cancelDrawOffer: function(ctrl) {
    if (ctrl.data.player.offeringDraw) return m('div.negotiation', [
      ctrl.trans('drawOfferSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentDrawOffer: function(ctrl) {
    if (ctrl.data.opponent.offeringDraw) return m('div.negotiation', [
      ctrl.trans('yourOpponentOffersADraw'),
      m('br'),
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'draw-yes', null)
      }, ctrl.trans('accept')),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  cancelTakebackProposition: function(ctrl) {
    if (ctrl.data.player.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('takebackPropositionSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentTakebackProposition: function(ctrl) {
    if (ctrl.data.opponent.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('yourOpponentProposesATakeback'),
      m('br'),
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.takebackYes),
      }, ctrl.trans('accept')),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  submitMove: function(ctrl) {
    if (ctrl.vm.moveToSubmit) return [
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.submitMove, true),
      }, 'Submit move'),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.submitMove, false)
      }, ctrl.trans('cancel')),
    ];
  },
  feedback: function(ctrl) {
    if (ctrl.vm.buttonFeedback) return m('div.button-feedback.loader.fast');
  },
  rematch: function(ctrl) {
    if ((status.finished(ctrl.data) || status.aborted(ctrl.data)) && !ctrl.data.tournament && !ctrl.data.simul && !ctrl.data.game.boosted) {
      if (ctrl.data.opponent.onGame || ctrl.data.game.speed === 'correspondence') {
        return m('a.button.hint--bottom', {
          'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
          onclick: partial(ctrl.socket.send, 'rematch-yes', null)
        }, ctrl.trans('rematch'));
      } else {
        return m('a.button.disabled', ctrl.trans('rematch'));
      }
    }
  },
  answerOpponentRematch: function(ctrl) {
    if (ctrl.data.opponent.offeringRematch) return [
      ctrl.trans('yourOpponentWantsToPlayANewGameWithYou'),
      m('a.glowed.button.fat.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        onclick: partial(ctrl.socket.send, 'rematch-yes', null),
      }, ctrl.trans('joinTheGame')),
      m('a.declineInvitation.button', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('declineInvitation'))
    ];
  },
  cancelRematch: function(ctrl) {
    if (ctrl.data.player.offeringRematch) return [
      ctrl.trans('rematchOfferSent'),
      m('br'),
      ctrl.trans('waitingForOpponent'),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('cancelRematchOffer'))
    ];
  },
  viewRematch: function(ctrl) {
    if (ctrl.data.game.rematch) return m('a.viewRematch.button.text[data-icon=v]', {
      href: router.game(ctrl.data.game.rematch, ctrl.data.opponent.color)
    }, ctrl.trans('viewRematch'));
  },
  joinRematch: function(ctrl) {
    if (ctrl.data.game.rematch) return [
      ctrl.trans('rematchOfferAccepted'),
      m('a.button.fat.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        href: router.game(ctrl.data.game.rematch, ctrl.data.opponent.color)
      }, ctrl.trans('joinTheGame'))
    ];
  },
  backToTournament: function(ctrl) {
    if (ctrl.data.tournament) return [
      m('a', {
        'data-icon': 'G',
        class: 'text button strong' + (ctrl.data.tournament.running ? ' glowed' : ''),
        href: '/tournament/' + ctrl.data.tournament.id
      }, ctrl.trans('backToTournament')),
      ctrl.data.tournament.running ? m('form', {
        method: 'post',
        action: '/tournament/' + ctrl.data.tournament.id + '/withdraw'
      }, m('button.text.button[data-icon=b]', ctrl.trans('withdraw'))) : null
    ];
  },
  viewTournament: function(ctrl) {
    if (ctrl.data.tournament) return m('a.viewTournament.button', {
      href: '/tournament/' + ctrl.data.tournament.id
    }, ctrl.trans('viewTournament'));
  },
  moretime: function(ctrl) {
    if (game.moretimeable(ctrl.data)) return m('a.moretime.hint--bottom-left', {
      'data-hint': ctrl.trans('giveNbSeconds', ctrl.data.clock.moretime),
      onclick: ctrl.socket.moreTime
    }, m('span[data-icon=O]'));
  },
  analysis: function(ctrl) {
    var hash = ctrl.replaying() ? '#' + ctrl.vm.ply : '';
    if (game.replayable(ctrl.data)) return m('a.button.replay_and_analyse', {
      onclick: partial(ctrl.socket.send, 'rematch-no', null),
      href: router.game(ctrl.data, analysisBoardOrientation(ctrl.data)) + hash
    }, ctrl.trans('analysis'));
  },
  newOpponent: function(ctrl) {
    if ((status.finished(ctrl.data) || status.aborted(ctrl.data)) && ctrl.data.game.source == 'lobby') {
      return m('a.button.hint--bottom', {
        href: '/?hook_like=' + ctrl.data.game.id,
        'data-hint': ctrl.trans('playWithAnotherOpponent')
      }, ctrl.trans('newOpponent'));
    }
  }
};
<commit_msg>add feedback when returning to tournament<commit_after>var chessground = require('chessground');
var classSet = chessground.util.classSet;
var game = require('game').game;
var status = require('game').status;
var partial = chessground.util.partial;
var router = require('game').router;
var m = require('mithril');

function analysisBoardOrientation(data) {
  if (data.game.variant.key === 'racingKings') {
    return 'white';
  } else {
    return data.player.color;
  }
}

module.exports = {
  standard: function(ctrl, condition, icon, hint, socketMsg, onclick) {
    // disabled if condition callback is provied and is falsy
    var enabled = !condition || condition(ctrl.data);
    return m('button', {
      class: 'button hint--bottom ' + socketMsg + classSet({
        ' disabled': !enabled
      }),
      'data-hint': ctrl.trans(hint),
      onclick: enabled ? onclick || partial(ctrl.socket.send, socketMsg, null) : null
    }, m('span', {
      'data-icon': icon
    }));
  },
  forceResign: function(ctrl) {
    if (!ctrl.data.opponent.ai && ctrl.data.clock && ctrl.data.opponent.isGone && game.resignable(ctrl.data))
      return m('div.force_resign_zone', [
        ctrl.trans('theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim'),
        m('br'),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'resign-force', null),
        }, ctrl.trans('forceResignation')),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'draw-force', null),
        }, ctrl.trans('forceDraw'))
      ]);
  },
  resignConfirm: function(ctrl) {
    return m('div.resign_confirm', [
      m('button.button.yes.active.hint--bottom', {
        'data-hint': ctrl.trans('resign'),
        onclick: partial(ctrl.resign, true)
      }, m('span', {
        'data-icon': 'b'
      })), m('button.button.no.hint--bottom', {
        'data-hint': ctrl.trans('cancel'),
        onclick: partial(ctrl.resign, false)
      }, m('span', {
        'data-icon': 'L'
      }))
    ]);
  },
  threefoldClaimDraw: function(ctrl) {
    if (ctrl.data.game.threefold) return m('div#claim_draw_zone', [
      ctrl.trans('threefoldRepetition'),
      m.trust(' '),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'draw-claim', null)
      }, ctrl.trans('claimADraw'))
    ]);
  },
  cancelDrawOffer: function(ctrl) {
    if (ctrl.data.player.offeringDraw) return m('div.negotiation', [
      ctrl.trans('drawOfferSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentDrawOffer: function(ctrl) {
    if (ctrl.data.opponent.offeringDraw) return m('div.negotiation', [
      ctrl.trans('yourOpponentOffersADraw'),
      m('br'),
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'draw-yes', null)
      }, ctrl.trans('accept')),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  cancelTakebackProposition: function(ctrl) {
    if (ctrl.data.player.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('takebackPropositionSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentTakebackProposition: function(ctrl) {
    if (ctrl.data.opponent.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('yourOpponentProposesATakeback'),
      m('br'),
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.takebackYes),
      }, ctrl.trans('accept')),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  submitMove: function(ctrl) {
    if (ctrl.vm.moveToSubmit) return [
      m('a.button.text[data-icon=E]', {
        onclick: partial(ctrl.submitMove, true),
      }, 'Submit move'),
      m('a.button.text[data-icon=L]', {
        onclick: partial(ctrl.submitMove, false)
      }, ctrl.trans('cancel')),
    ];
  },
  feedback: function(ctrl) {
    if (ctrl.vm.buttonFeedback) return m('div.button-feedback.loader.fast');
  },
  rematch: function(ctrl) {
    if ((status.finished(ctrl.data) || status.aborted(ctrl.data)) && !ctrl.data.tournament && !ctrl.data.simul && !ctrl.data.game.boosted) {
      if (ctrl.data.opponent.onGame || ctrl.data.game.speed === 'correspondence') {
        return m('a.button.hint--bottom', {
          'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
          onclick: partial(ctrl.socket.send, 'rematch-yes', null)
        }, ctrl.trans('rematch'));
      } else {
        return m('a.button.disabled', ctrl.trans('rematch'));
      }
    }
  },
  answerOpponentRematch: function(ctrl) {
    if (ctrl.data.opponent.offeringRematch) return [
      ctrl.trans('yourOpponentWantsToPlayANewGameWithYou'),
      m('a.glowed.button.fat.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        onclick: partial(ctrl.socket.send, 'rematch-yes', null),
      }, ctrl.trans('joinTheGame')),
      m('a.declineInvitation.button', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('declineInvitation'))
    ];
  },
  cancelRematch: function(ctrl) {
    if (ctrl.data.player.offeringRematch) return [
      ctrl.trans('rematchOfferSent'),
      m('br'),
      ctrl.trans('waitingForOpponent'),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('cancelRematchOffer'))
    ];
  },
  viewRematch: function(ctrl) {
    if (ctrl.data.game.rematch) return m('a.viewRematch.button.text[data-icon=v]', {
      href: router.game(ctrl.data.game.rematch, ctrl.data.opponent.color)
    }, ctrl.trans('viewRematch'));
  },
  joinRematch: function(ctrl) {
    if (ctrl.data.game.rematch) return [
      ctrl.trans('rematchOfferAccepted'),
      m('a.button.fat.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        href: router.game(ctrl.data.game.rematch, ctrl.data.opponent.color)
      }, ctrl.trans('joinTheGame'))
    ];
  },
  backToTournament: function(ctrl) {
    if (ctrl.data.tournament) return [
      m('a', {
        'data-icon': 'G',
        class: 'text button strong' + (ctrl.data.tournament.running ? ' glowed' : ''),
        href: '/tournament/' + ctrl.data.tournament.id,
        onclick: ctrl.setRedirecting
      }, ctrl.trans('backToTournament')),
      ctrl.data.tournament.running ? m('form', {
        method: 'post',
        action: '/tournament/' + ctrl.data.tournament.id + '/withdraw'
      }, m('button.text.button[data-icon=b]', ctrl.trans('withdraw'))) : null
    ];
  },
  viewTournament: function(ctrl) {
    if (ctrl.data.tournament) return m('a.viewTournament.button', {
      href: '/tournament/' + ctrl.data.tournament.id
    }, ctrl.trans('viewTournament'));
  },
  moretime: function(ctrl) {
    if (game.moretimeable(ctrl.data)) return m('a.moretime.hint--bottom-left', {
      'data-hint': ctrl.trans('giveNbSeconds', ctrl.data.clock.moretime),
      onclick: ctrl.socket.moreTime
    }, m('span[data-icon=O]'));
  },
  analysis: function(ctrl) {
    var hash = ctrl.replaying() ? '#' + ctrl.vm.ply : '';
    if (game.replayable(ctrl.data)) return m('a.button.replay_and_analyse', {
      onclick: partial(ctrl.socket.send, 'rematch-no', null),
      href: router.game(ctrl.data, analysisBoardOrientation(ctrl.data)) + hash
    }, ctrl.trans('analysis'));
  },
  newOpponent: function(ctrl) {
    if ((status.finished(ctrl.data) || status.aborted(ctrl.data)) && ctrl.data.game.source == 'lobby') {
      return m('a.button.hint--bottom', {
        href: '/?hook_like=' + ctrl.data.game.id,
        'data-hint': ctrl.trans('playWithAnotherOpponent')
      }, ctrl.trans('newOpponent'));
    }
  }
};
<|endoftext|>


<commit_before>'use strict';

const test = require('ava').test;
const babel = require('babel-core');
const babelTypes = require('babel-types');

const BabelPluginExportToFunction = require('../../lib/BabelPluginExportToFunction');

test('BabelPluginExportToFunction should wrap a function without arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function expression with multiple arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config, myArg1, myArg2, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerArg1, __bundlerArg2, __bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, myArg1, myArg2, callback) {};',
        '  rule(__bundlerConfig, __bundlerArg1, __bundlerArg2, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function and assign it to module.exports', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral(), { commonjs: true });
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'module.exports = function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '};'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function declaration', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'function myRule(config, arg1, callback) {}',
        'var script = myRule;',
        'exports.default = script;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerArg1, __bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  function myRule(config, arg1, callback) {}',
        '  var script = myRule;',
        '  script(__bundlerConfig, __bundlerArg1, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should inject config ast', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = "testconfig";',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should throw on invalid export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'function myRule() { exports.default = function (test) {}; }';
    t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));
});

test('BabelPluginExportToFunction should throw on variable export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'var a = "test"; exports.default = a; }';
    t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));
});

test('BabelPluginExportToFunction should throw on not enough arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config) {}',
        'exports.default = rule;'
    ].join('\n');

    t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));
});

test('BabelPluginExportToFunction should throw on a missing export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'function myRule() {}';
    const error = t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }), TypeError);

    t.is(error.message, 'unknown: auth0-bundler is missing default export in module');
});
<commit_msg>Assert error messages in each test<commit_after>'use strict';

const test = require('ava').test;
const babel = require('babel-core');
const babelTypes = require('babel-types');

const BabelPluginExportToFunction = require('../../lib/BabelPluginExportToFunction');

test('BabelPluginExportToFunction should wrap a function without arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function expression with multiple arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config, myArg1, myArg2, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerArg1, __bundlerArg2, __bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, myArg1, myArg2, callback) {};',
        '  rule(__bundlerConfig, __bundlerArg1, __bundlerArg2, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function and assign it to module.exports', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral(), { commonjs: true });
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'module.exports = function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '};'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should wrap a function declaration', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'function myRule(config, arg1, callback) {}',
        'var script = myRule;',
        'exports.default = script;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerArg1, __bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = null;',
        '  function myRule(config, arg1, callback) {}',
        '  var script = myRule;',
        '  script(__bundlerConfig, __bundlerArg1, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should inject config ast', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = [
        'var rule = function myRule(config, callback) {}',
        'exports.default = rule;'
    ].join('\n');
    const expected = [
        'function __bundlerWrapper(__bundlerCallback) {',
        '  \'use strict\';',
        '',
        '  var __bundlerConfig = "testconfig";',
        '  var rule = function myRule(config, callback) {};',
        '  rule(__bundlerConfig, __bundlerCallback);',
        '}'
    ].join('\n');

    t.is(babel.transform(code, {
        plugins: [ exportToFunction ]
    }).code, expected);
});

test('BabelPluginExportToFunction should throw on invalid export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'function myRule() { exports.default = function (test) {}; }';
    const error = t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));

    t.is(error.message, 'unknown: auth0-bundler is missing default export in module');
});

test('BabelPluginExportToFunction should throw on variable export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'const a = "test"; exports.default = a;';
    const error = t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));

    t.is(error.message, 'unknown: auth0-bundler is missing default export in module');
});

test('BabelPluginExportToFunction should throw on not enough arguments', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.nullLiteral());
    const code = [
        'var rule = function myRule(config) {}',
        'exports.default = rule;'
    ].join('\n');

    const error = t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }));

    t.is(error.message, 'unknown: auth0-bundler is missing default export in module');
});

test('BabelPluginExportToFunction should throw on a missing export', (t) => {
    const exportToFunction = new BabelPluginExportToFunction(babelTypes.stringLiteral('testconfig'));
    const code = 'function myRule() {}';
    const error = t.throws(() => babel.transform(code, { plugins: [ exportToFunction ] }), TypeError);

    t.is(error.message, 'unknown: auth0-bundler is missing default export in module');
});
<|endoftext|>


<commit_before>//Export general modules
export {version} from "./src/version.js";
export * from "./src/global.js";

//Import global styles
import "./src/style.scss";

//Export helpers
export * from "./src/global.js";
export * from "./src/helpers.js";
export * from "./src/ready.js";

//Export basic components
export * from "./src/core/index.js";
export * from "./src/experiments/index.js";
export * from "./src/future/index.js";
export * from "./src/icon/index.js";
export * from "./src/layout/index.js";
export * from "./src/widgets/index.js";

//Loaders
export * from "./src/loaders/basic-loader/index.js";
export * from "./src/loaders/dna-loader/index.js";

//Big components
export * from "./src/datatable/index.js";

//Export testing components
export * from "./src/test/index.js";

//Export utils components
export * from "./src/utils/choose.js";
export * from "./src/utils/for-each.js";
export * from "./src/utils/if.js";
export * from "./src/utils/renderer.js";

<commit_msg>neutrine: export for component<commit_after>//Export general modules
export {version} from "./src/version.js";
export * from "./src/global.js";

//Import global styles
import "./src/style.scss";

//Export helpers
export * from "./src/global.js";
export * from "./src/helpers.js";
export * from "./src/ready.js";

//Export basic components
export * from "./src/core/index.js";
export * from "./src/experiments/index.js";
export * from "./src/future/index.js";
export * from "./src/icon/index.js";
export * from "./src/layout/index.js";
export * from "./src/widgets/index.js";

//Loaders
export * from "./src/loaders/basic-loader/index.js";
export * from "./src/loaders/dna-loader/index.js";

//Big components
export * from "./src/datatable/index.js";

//Export testing components
export * from "./src/test/index.js";

//Export utils components
export * from "./src/utils/choose.js";
export * from "./src/utils/for.js";
export * from "./src/utils/for-each.js";
export * from "./src/utils/if.js";
export * from "./src/utils/renderer.js";

<|endoftext|>